Skip to content

Commit

Permalink
Add Contract support for strkey-style contract IDs (#612)
Browse files Browse the repository at this point in the history
* new Contract('C123...abc') support

* review feedback
  • Loading branch information
Paul Bellamy authored May 30, 2023
1 parent 4a39274 commit 33dcef5
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 22 deletions.
32 changes: 26 additions & 6 deletions src/contract.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Operation } from './operation';
import xdr from './xdr';
import { StrKey } from './strkey';

/**
* Create a new Contract object.
Expand All @@ -12,23 +13,42 @@ import xdr from './xdr';
* @constructor
*
* @param {string} contractId - ID of the contract (ex.
* `CA3D5KRYM6CB7OWQ6TWYRR3Z4T7GNZLKERYNZGGA5SOAOPIFY6YQGAXE`, or as a
* 32-byte hex string
* `000000000000000000000000000000000000000000000000000000000000000001`).
*/
// TODO: Support contract deployment, maybe?
export class Contract {
// TODO: Figure out contract owner/id stuff here. How should we represent that?
constructor(contractId) {
// TODO: Add methods based on the contractSpec (or do that elsewhere?)
this._id = Buffer.from(contractId, 'hex');
try {
// First, try it as a strkey
this._id = StrKey.decodeContract(contractId);
} catch (_) {
// If that fails, try it as a hex string
// TODO: Add methods based on the contractSpec (or do that elsewhere?)
const b = Buffer.from(contractId, 'hex');
if (b.length !== 32) {
throw new Error('Invalid contract ID');
}
this._id = b;
}
}

/**
* Returns Stellar contract ID as a hex string, ex.
* Returns Stellar contract ID as a strkey, or hex string, ex.
* `000000000000000000000000000000000000000000000000000000000000000001`.
* @param {'hex'|'strkey'} format - format of output, defaults to 'strkey'
* @returns {string}
*/
contractId() {
return this._id.toString('hex');
contractId(format = 'strkey') {
switch (format) {
case 'strkey':
return StrKey.encodeContract(this._id);
case 'hex':
return this._id.toString('hex');
default:
throw new Error(`Invalid format: ${format}`);
}
}

/**
Expand Down
52 changes: 37 additions & 15 deletions test/unit/contract_test.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,42 @@
describe('Contract.getFootprint', function () {
it('includes the correct contract code footprint', function () {
let contractId = '0'.repeat(63) + '1';
describe('Contract', function () {
describe('constructor', function () {
it('parses strkeys', function () {
let contractId = 'CA3D5KRYM6CB7OWQ6TWYRR3Z4T7GNZLKERYNZGGA5SOAOPIFY6YQGAXE';
let contract = new StellarBase.Contract(contractId);
expect(contract.contractId('strkey')).to.equal(contractId);
});

let contract = new StellarBase.Contract(contractId);
expect(contract.contractId()).to.equal(contractId);
it('parses hex addresses', function () {
let contractId = '0'.repeat(63) + '1';
let contract = new StellarBase.Contract(contractId);
expect(contract.contractId('hex')).to.equal(contractId);
});

const fp = contract.getFootprint();
it('parses throws on invalid ids', function () {
expect(() => {
new StellarBase.Contract('foobar')
}).to.throw();
});
});

describe('getFootprint', function () {
it('includes the correct contract code footprint', function () {
let contractId = '0'.repeat(63) + '1';

let contract = new StellarBase.Contract(contractId);
expect(contract.contractId('hex')).to.equal(contractId);

const fp = contract.getFootprint();

let expected = new StellarBase.xdr.LedgerKey.contractData(
new StellarBase.xdr.LedgerKeyContractData({
contractId: Buffer.from(contractId, 'hex'),
key: StellarBase.xdr.ScVal.scvLedgerKeyContractExecutable()
})
)
.toXDR()
.toString('base64');
expect(fp.toXDR().toString('base64')).to.equal(expected);
let expected = new StellarBase.xdr.LedgerKey.contractData(
new StellarBase.xdr.LedgerKeyContractData({
contractId: Buffer.from(contractId, 'hex'),
key: StellarBase.xdr.ScVal.scvLedgerKeyContractExecutable()
})
)
.toXDR()
.toString('base64');
expect(fp.toXDR().toString('base64')).to.equal(expected);
});
});
});
2 changes: 1 addition & 1 deletion types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export class Address {

export class Contract {
constructor(contractId: string);
contractId(): string;
contractId(format?: 'hex' | 'strkey'): string;
call(method: string, ...params: xdr.ScVal[]): xdr.Operation<Operation.InvokeHostFunction>;
}

Expand Down

0 comments on commit 33dcef5

Please sign in to comment.