Skip to content

Commit

Permalink
refactor(contract)!: add $createDelegationSignature to contract ins…
Browse files Browse the repository at this point in the history
…tance

BREAKING CHANGE: `createAensDelegationSignature`, `createOracleDelegationSignature` removed
Use `contract.$createDelegationSignature` instead.
  • Loading branch information
davidyuk committed Aug 12, 2022
1 parent 3bfbb52 commit 24699f1
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 140 deletions.
4 changes: 2 additions & 2 deletions src/AeSdkBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as chainMethods from './chain';
import * as aensMethods from './aens';
import * as spendMethods from './spend';
import * as oracleMethods from './oracle';
import * as contractMethods from './contract/methods';
import getContractInstance from './contract/aci';
import * as contractGaMethods from './contract/ga';
import { _buildTx } from './tx';
import { mapObject } from './utils/other';
Expand Down Expand Up @@ -260,7 +260,7 @@ const methods = {
...aensMethods,
...spendMethods,
...oracleMethods,
...contractMethods,
getContractInstance,
...contractGaMethods,
} as const;

Expand Down
2 changes: 1 addition & 1 deletion src/account/Generalized.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {
} from '../utils/errors';
import { decode, Encoded } from '../utils/encoder';
import { getAccount } from '../chain';
import { getContractInstance } from '../contract/methods';
import getContractInstance from '../contract/aci';
import { _buildTx } from '../tx';
import { Tag } from '../tx/builder/constants';
import { buildTx } from '../tx/builder';
Expand Down
66 changes: 66 additions & 0 deletions src/contract/aci.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/

/**
* Contract module - routines to interact with the æternity contract
*
* High level documentation of the contracts are available at
* https://github.com/aeternity/protocol/tree/master/contracts and
*/

import { Encoder as Calldata } from '@aeternity/aepp-calldata';
import { DRY_RUN_ACCOUNT } from '../tx/builder/schema';
import { Tag, AensName } from '../tx/builder/constants';
Expand Down Expand Up @@ -48,6 +56,8 @@ import {
getAccount, getContract, getContractByteCode, getKeyBlock, resolveName, txDryRun,
} from '../chain';
import AccountBase from '../account/Base';
import { concatBuffers } from '../utils/other';
import { isNameValid, produceNameId } from '../tx/builder/helpers';

interface FunctionACI {
arguments: any[];
Expand Down Expand Up @@ -138,6 +148,10 @@ export interface ContractInstance {
decodeEvents: (
events: Event[], options?: { omitUnknown?: boolean; contractAddressToName?: any }
) => DecodedEvent[];
$createDelegationSignature: (
ids?: Array<Encoded.Any | AensName>,
_options?: { omitAddress?: boolean; onAccount?: AccountBase },
) => Promise<Uint8Array>;
methods: any;
}

Expand Down Expand Up @@ -231,6 +245,58 @@ export default async function getContractInstance({
/* eslint-enable @typescript-eslint/no-unused-vars */
/* eslint-enable @typescript-eslint/no-empty-function */
methods: undefined,
/**
* Helper to generate a signature to delegate
* - pre-claim/claim/transfer/revoke of a name to a contract.
* - register/extend/respond of an Oracle to a contract.
* @category contract
* @param ids - The list of id's to prepend
* @param _options - Options
* @param _options.omitAddress - Prepend delegation signature with an account address
* @param _options.onAccount - Account to use
* @returns Signature
* @example
* ```js
* const aeSdk = new AeSdk({ ... })
* const contract = await aeSdk.getContractInstance({ address: 'ct_asd2ks...' })
* const aensName = 'example.chain'
* const onAccount = new MemoryAccount(...) // Sign with a specific account
* // Preclaim signature
* const preclaimSig = await contract.$createDelegationSignature([], { onAccount })
* // Claim, transfer and revoke signature
* const aensDelegationSig = await contract
* .$createDelegationSignature([aensName], { onAccount })
* ```
* @example
* ```js
* const aeSdk = new AeSdk({ ... })
* const contract = await aeSdk.getContractInstance({ address: 'ct_asd2ks...' })
* const oracleQueryId = 'oq_...'
* const onAccount = new MemoryAccount(...) // Sign with a specific account
* // Oracle register and extend signature
* const oracleDelegationSig = await contract.$createDelegationSignature([], { onAccount })
* // Oracle respond signature
* const respondSig = await contract
* .$createDelegationSignature([oracleQueryId], { onAccount, omitAddress: true })
* ```
*/
async $createDelegationSignature(
ids: Array<Encoded.Any | AensName> = [],
_options?: { omitAddress?: boolean; onAccount?: AccountBase },
): Promise<Uint8Array> {
const options = { ...instance.options, ..._options };
const contractId = instance.deployInfo.address;
if (contractId == null) throw new MissingContractAddressError('Can\'t create delegation signature without address');
return options.onAccount.sign(
concatBuffers([
Buffer.from(await options.onNode.getNetworkId()),
...options.omitAddress === true ? [] : [decode(options.onAccount.address)],
...ids.map((e) => (isNameValid(e) ? produceNameId(e) : e)).map((e) => decode(e)),
decode(contractId),
]),
options,
);
},
};

if (validateBytecode != null) {
Expand Down
2 changes: 1 addition & 1 deletion src/contract/ga.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { decode, Encoded } from '../utils/encoder';
import { IllegalArgumentError } from '../utils/errors';
import { concatBuffers } from '../utils/other';
import AccountBase from '../account/Base';
import { getContractInstance } from './methods';
import getContractInstance from './aci';
import { send, SendOptions } from '../spend';
import Node from '../Node';
import { getAccount } from '../chain';
Expand Down
117 changes: 0 additions & 117 deletions src/contract/methods.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export * from './utils/amount-formatter';
export * from './utils/hd-wallet';
export { encode, decode, Encoding } from './utils/encoder';
export * from './aens';
export * from './contract/methods';
export { default as getContractInstance } from './contract/aci';
export * from './oracle';
export * from './spend';
export * from './contract/ga';
Expand Down
30 changes: 12 additions & 18 deletions test/integration/contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -319,32 +319,30 @@ describe('Contract', () => {
});

describe('AENS operation delegation', () => {
let contractId: Encoded.ContractAddress;
const name = randomName(15);
const salt = genSalt();
let owner: Encoded.AccountAddress;
let newOwner: Encoded.AccountAddress;
let delegationSignature: string;
let delegationSignature: Uint8Array;

before(async () => {
contract = await aeSdk.getContractInstance({ sourceCode: aensDelegationContract });
await contract.deploy();
if (contract.deployInfo.address == null) throw new UnexpectedTsError();
contractId = contract.deployInfo.address;
[owner, newOwner] = aeSdk.addresses();
});

it('preclaims', async () => {
const commitmentId = commitmentHash(name, salt);
// TODO: provide more convenient way to create the decoded commitmentId ?
const commitmentIdDecoded = decode(commitmentId);
const preclaimSig = await aeSdk.createAensDelegationSignature(contractId);
const preclaimSig = await contract.$createDelegationSignature();
const preclaim = await contract.methods
.signedPreclaim(owner, commitmentIdDecoded, preclaimSig);
preclaim.result.returnType.should.be.equal('ok');
await aeSdk.awaitHeight(2 + await aeSdk.getHeight());
// signature for any other name related operations
delegationSignature = await aeSdk.createAensDelegationSignature(contractId, { name });
delegationSignature = await contract.$createDelegationSignature([name]);
});

it('claims', async () => {
Expand Down Expand Up @@ -378,35 +376,31 @@ describe('Contract', () => {
});

it('revokes', async () => {
const revokeSig = await aeSdk.createAensDelegationSignature(
contractId,
{ name, onAccount: newOwner },
);
const revokeSig = await contract
.$createDelegationSignature([name], { onAccount: aeSdk.accounts[newOwner] });
const revoke = await contract.methods.signedRevoke(newOwner, name, revokeSig);
revoke.result.returnType.should.be.equal('ok');
await expect(aeSdk.aensQuery(name)).to.be.rejectedWith(Error);
});
});

describe('Oracle operation delegation', () => {
let contractId: Encoded.ContractAddress;
let oracle: Awaited<ReturnType<typeof aeSdk.getOracleObject>>;
let oracleId: Encoded.OracleAddress;
let queryObject: Awaited<ReturnType<typeof aeSdk.getQueryObject>>;
let delegationSignature: string;
let delegationSignature: Uint8Array;
const queryFee = 500000;
const ttl = { RelativeTTL: [50] };

before(async () => {
contract = await aeSdk.getContractInstance({ sourceCode: oracleContract });
await contract.deploy();
if (contract.deployInfo.address == null) throw new UnexpectedTsError();
contractId = contract.deployInfo.address;
oracleId = encode(decode(aeSdk.address), Encoding.OracleAddress);
});

it('registers', async () => {
delegationSignature = await aeSdk.createOracleDelegationSignature(contractId);
delegationSignature = await contract.$createDelegationSignature();
const oracleRegister = await contract.methods
.signedRegisterOracle(aeSdk.address, delegationSignature, queryFee, ttl);
oracleRegister.result.returnType.should.be.equal('ok');
Expand Down Expand Up @@ -436,14 +430,14 @@ describe('Contract', () => {

it('responds to query', async () => {
const r = 'Hi!';
const queryId = queryObject.id;
// TODO type should be corrected in node api
const queryId = queryObject.id as Encoded.OracleQueryId;
aeSdk.selectAccount(aeSdk.addresses()[1]);
const respondSig = await aeSdk.createOracleDelegationSignature(contractId, { queryId });
const respondSig = await contract
.$createDelegationSignature([queryId], { omitAddress: true });
const response = await contract.methods.respond(oracle.id, queryObject.id, respondSig, r);
response.result.returnType.should.be.equal('ok');
// TODO type should be corrected in node api
const queryObject2 = await aeSdk
.getQueryObject(oracle.id, queryObject.id as Encoded.OracleQueryId);
const queryObject2 = await aeSdk.getQueryObject(oracle.id, queryId);
queryObject2.decodedResponse.should.be.equal(r);
});
});
Expand Down

0 comments on commit 24699f1

Please sign in to comment.