Skip to main content
Last updated

Kadena client libraries

The Kadena client is a collection`of libraries, functions, and utilities written in TypeScript to provide a familiar application programming interface (API) for interacting with smart contracts and the Kadena network.

For a list of released Kadena client packages, see the kadena.js repository. This section provides basic reference information for the @kadena/client library. The @kadena/client library provides a TypeScript-based API for interacting with smart contracts and Chainweb nodes on the Kadena network. The library includes modules to help you perform the following types of common tasks:

  • Create commands
  • Sign transactions
  • Submit transactions
  • Query transaction results

Pact.modules

Use Pact.modules to call smart contract functions with specified arguments.

typescript
import { Pact } from `@kadena/client`; Pact.modules[`${namespace}.${moduleName}`][functionName](...args);
typescript
import { Pact } from `@kadena/client`; Pact.modules[`${namespace}.${moduleName}`][functionName](...args);
ParameterTypeDescription
...argsPactValue[]List of arguments.

Valid PactValue types:

typescript
type PactValue =  | string  | number  | boolean  | Date  | { int: string }  | { decimal: string }  | PactValue[]  | Record<string, PactValue>;
typescript
type PactValue =  | string  | number  | boolean  | Date  | { int: string }  | { decimal: string }  | PactValue[]  | Record<string, PactValue>;

Examples

To create the code for the coin.transfer function:

typescript
import { Pact } from `@kadena/client`; const code = Pact.modules.coin.transfer("alice", "bob", { decimal: '1.1' });// code === '(coin.transfer "alice" "bob" 1.1)' 
typescript
import { Pact } from `@kadena/client`; const code = Pact.modules.coin.transfer("alice", "bob", { decimal: '1.1' });// code === '(coin.transfer "alice" "bob" 1.1)' 

To create the code for the free.my-module.my-function function that converts a list, objects, and date to valid Pact code:

typescript
import { Pact } from `@kadena/client`; const code = Pact.modules["free.my-module"].["my-function"](["first", { time: new Date() }]);// code === '(free.my-module.my-function ["first" {"time" : (time "2023-07-20T14:55:11Z")} ])' 
typescript
import { Pact } from `@kadena/client`; const code = Pact.modules["free.my-module"].["my-function"](["first", { time: new Date() }]);// code === '(free.my-module.my-function ["first" {"time" : (time "2023-07-20T14:55:11Z")} ])' 

Pact.builder.execution

Use Pact.builder to create an execution (exec) command object, IPactCommand.payload.exec.code.

typescript
Pact.builder.execution(...codes): IBuilder
typescript
Pact.builder.execution(...codes): IBuilder
ParameterTypeDescription
...codesstring[]List of input for a function.

Examples

To use strings for the command code:

typescript
const builder: IBuilder = Pact.builder.execution(  `(coin.transfer "alice" "bob" 1.1)`,);
typescript
const builder: IBuilder = Pact.builder.execution(  `(coin.transfer "alice" "bob" 1.1)`,);

To use Pact.modules for the command code:

typescript
const builder: IBuilder = Pact.builder.execution(  Pact.modules.coin.transfer('alice', 'bob', { decimal: '1.1' }),);
typescript
const builder: IBuilder = Pact.builder.execution(  Pact.modules.coin.transfer('alice', 'bob', { decimal: '1.1' }),);

Pact.builder.continuation

Use Pact.builder to create a continuation command object, IPactCommand.payload.cont.

typescript
Pact.builder.continuation(contData): IBuilder
typescript
Pact.builder.continuation(contData): IBuilder
ParameterTypeDescription
contDataobjectContinuation data includes a unique defpact identifier, whether the transactions rolls back a previous transaction, the transaction step that the continuation represents with the first step being step 0, and a simple payment verification proof if one is generated by calling the /spv endpoint.

The contData object consists of the following properties:

json
{     pactId: string,     rollback: boolean,     step: number,     data?: Record<string, any>,     proof?: null \| string} 
json
{     pactId: string,     rollback: boolean,     step: number,     data?: Record<string, any>,     proof?: null \| string} 

Example

The coin.cross-chain function is a defpact multi-step transaction that burns tokens in the source chain and mints tokens in the destination chain. After the first step completes successfully, you can call the second step by using the continuation command object.

TS
const builder: IBuilder = Pact.builder.continuation({  pactId,  rollback: false,  step:1,  proof: spvProof})
TS
const builder: IBuilder = Pact.builder.continuation({  pactId,  rollback: false,  step:1,  proof: spvProof})

addSigner

Use addSigner to add public keys and capabilities for a transaction signer to a command. You can call addSigner multiple times to add multiple signers to the transaction.

typescript
Pact.builder.execution(...codes).addSigner(signerOrSignersList, capabilityCallback): IBuilder
typescript
Pact.builder.execution(...codes).addSigner(signerOrSignersList, capabilityCallback): IBuilder
ParameterTypeDescription
signerstring or objectPublic key of the signer or the signer object (this can also be a list of signers if all of the signers sign for the same capabilities).
capabilityCallback(signFor) => ReturnType[]Allows you to scope what the signer is signing for to a specific list of capabilities.

The signer object consists of the following properties:

json
{  pubKey: string;  scheme?: 'ED25519' \| 'ETH' \| 'WebAuthn';   address?: string; }
json
{  pubKey: string;  scheme?: 'ED25519' \| 'ETH' \| 'WebAuthn';   address?: string; }

Chainweb supports the following signature schemes for public keys:

  • ED25519
  • WebAuthn
  • ETH

The default signature scheme is ED25519. You can pass just the public key if the signature scheme is ED25519. If the scheme is not ED25519, you must pass a signer object that includes the pubic key and the signature scheme.

Examples

To add a signer public key for a coin contract transfer:

typescript
// ED25519 keyconst alicePublicKey =  'e7f4da07b1d200f6e45aa6492afed6819297a97563859a5f0df9c54f5abd4aab'; Pact.builder  .execution(Pact.modules.coin.transfer('alice', 'bob', { decimal: '1.1' }))  .addSigner(alicePublicKey, (signFor) => [    signFor('coin.TRANSFER', 'alice', 'bob', { decimal: '1.1' }),  ]);
typescript
// ED25519 keyconst alicePublicKey =  'e7f4da07b1d200f6e45aa6492afed6819297a97563859a5f0df9c54f5abd4aab'; Pact.builder  .execution(Pact.modules.coin.transfer('alice', 'bob', { decimal: '1.1' }))  .addSigner(alicePublicKey, (signFor) => [    signFor('coin.TRANSFER', 'alice', 'bob', { decimal: '1.1' }),  ]);

To add a signer that uses the WebAuthn scheme:

typescript
Pact.builder  .execution(Pact.modules.coin.transfer('alice', 'bob', { decimal: '1.1' }))  .addSigner({ pubKey: webAuthnPublicKey, scheme: 'WebAuthn' }, (signFor) => [    signFor('coin.TRANSFER', 'alice', 'bob', { decimal: '1.1' }),  ]);
typescript
Pact.builder  .execution(Pact.modules.coin.transfer('alice', 'bob', { decimal: '1.1' }))  .addSigner({ pubKey: webAuthnPublicKey, scheme: 'WebAuthn' }, (signFor) => [    signFor('coin.TRANSFER', 'alice', 'bob', { decimal: '1.1' }),  ]);

To add a list of signers with no capabilities:

typescript
Pact.builder  .execution('(free.my-module.my-function)')  .addSigner([    'ED25519_publicKey',    { pubKey: 'WebAuthn_publicKey', scheme: 'WebAuthn' },  ]);
typescript
Pact.builder  .execution('(free.my-module.my-function)')  .addSigner([    'ED25519_publicKey',    { pubKey: 'WebAuthn_publicKey', scheme: 'WebAuthn' },  ]);

To add a list of signers with similar capabilities:

typescript
Pact.builder  .execution(Pact.modules.coin.transfer('alice', 'bob', { decimal: '1.1' }))  // e.g., Alice's account is guarded by two keys  .addSigner(['first_publicKey', 'second_publicKey'], (signFor) => [    signFor('coin.TRANSFER', 'alice', 'bob', { decimal: '1.1' }),  ]); const equivalentPactCommand = {  payload: {    exec: {      code: '(coin.transfer "alice" "bob" 1.1 )',      data: {},    },  },  signers: [    {      pubKey: 'first_publicKey',      scheme: 'ED25519',      clist: [        { name: 'coin.TRANSFER', args: ['alice', 'bob', { decimal: '1.1' }] },      ],    },    {      pubKey: 'second_publicKey',      scheme: 'ED25519',      clist: [        { name: 'coin.TRANSFER', args: ['alice', 'bob', { decimal: '1.1' }] },      ],    },  ],};
typescript
Pact.builder  .execution(Pact.modules.coin.transfer('alice', 'bob', { decimal: '1.1' }))  // e.g., Alice's account is guarded by two keys  .addSigner(['first_publicKey', 'second_publicKey'], (signFor) => [    signFor('coin.TRANSFER', 'alice', 'bob', { decimal: '1.1' }),  ]); const equivalentPactCommand = {  payload: {    exec: {      code: '(coin.transfer "alice" "bob" 1.1 )',      data: {},    },  },  signers: [    {      pubKey: 'first_publicKey',      scheme: 'ED25519',      clist: [        { name: 'coin.TRANSFER', args: ['alice', 'bob', { decimal: '1.1' }] },      ],    },    {      pubKey: 'second_publicKey',      scheme: 'ED25519',      clist: [        { name: 'coin.TRANSFER', args: ['alice', 'bob', { decimal: '1.1' }] },      ],    },  ],};

addData

Use addData to add data to the IPactCommand.payload.exec.data or IPactCommand.payload.cont.data command. This data is readable in the smart contract later. You can also use this data in the code you set in the command.

typescript
Pact.builder  .execution(...codes)  .addData(key, value): IBuilder
typescript
Pact.builder  .execution(...codes)  .addData(key, value): IBuilder
ParameterTypeDescription
keystringThe key associated with the data you're sending.
valuePactValueData that you want to send.

Examples

To transfer with parameters in data:

typescript
Pact.builder  .execution('(coin.transfer (read-string "sender") (read-string "receiver") 1.1)')  .addData("sender", sender)  .addData("receiver", sender): IBuilder
typescript
Pact.builder  .execution('(coin.transfer (read-string "sender") (read-string "receiver") 1.1)')  .addData("sender", sender)  .addData("receiver", sender): IBuilder

To use transfer-create and send the receiver guard:

typescript
Pact.builder  .execution(    '(coin.transfer-create "alice" "bob" (read-keyset "bob-guard") 1.1)',  )  .addData('bob-guard', {    keys: ['bob-public-key'],    pred: 'keys-all',  });
typescript
Pact.builder  .execution(    '(coin.transfer-create "alice" "bob" (read-keyset "bob-guard") 1.1)',  )  .addData('bob-guard', {    keys: ['bob-public-key'],    pred: 'keys-all',  });

addKeyset

Use addKeyset as an alternative to the addData method to add a keyset to a command.

typescript
Pact.builder  .execution(...codes)  .addKeyset(name, pred, ...keys): IBuilder
typescript
Pact.builder  .execution(...codes)  .addKeyset(name, pred, ...keys): IBuilder
ParameterTypeDescription
namestringThe name associated with the keyset.
predstringOne of the built-in keys-all, keys-2, keys-any predicate functions or a user-defined predicate function.
...keys...string[]List of public keys in the keyset.

Examples

To use readKeyset and addKeyset helper functions with transfer-create:

typescript
Pact.builder  .execution(    Pact.modules.coin['transfer-create'](      'alice',      'bob',      readKeyset('bob-guard'),      { decimal: '1.1' },    ),  )  .addKeyset('bob-guard', 'keys-all', 'bob-public-key');
typescript
Pact.builder  .execution(    Pact.modules.coin['transfer-create'](      'alice',      'bob',      readKeyset('bob-guard'),      { decimal: '1.1' },    ),  )  .addKeyset('bob-guard', 'keys-all', 'bob-public-key');

To use transfer-create as string code:

typescript
Pact.builder  .execution(    '(coin.transfer-create "alice" "bob" (readKeyset "bob-guard") 1.1)',  )  .addKeyset('bob-guard', 'keys-all', 'bob-public-key');
typescript
Pact.builder  .execution(    '(coin.transfer-create "alice" "bob" (readKeyset "bob-guard") 1.1)',  )  .addKeyset('bob-guard', 'keys-all', 'bob-public-key');

setMeta

Use setMeta to add metadata to a command.

typescript
Pact.builder  .execution(...codes)  .setMeta(meta): IBuilder
typescript
Pact.builder  .execution(...codes)  .setMeta(meta): IBuilder
ParameterTypeDescription
metaobjectAdd a metadata object to the command.

The meta object consists of the following properties:

PropertyTypeDefault valueDescription
chainIdstringundefinedChain identifier for the chain. Valid values are from 0 to 19.
senderAccountstringundefinedThe account name that you want to pay transaction fees from.
gasLimitnumber2500Maximum units of gas that you want to allow to be deducted when running the transaction.
gasPricenumber1.0e-8Price of each gas unit based on KDA (e.g., 0.0000001).
ttlnumber28800Time-to-live (ttl) for the transaction to be valid in seconds. The default value is 8 hours.
creationTimenumberDate.now() / 1000Transaction creation time in seconds.

Examples

typescript
Pact.builder  .execution('(coin.transfer "alice" "bob" 1.1)')  // "bob is paying gas fee"  .setMeta({ chainId: "02", senderAccount: "bob" }): IBuilder;
typescript
Pact.builder  .execution('(coin.transfer "alice" "bob" 1.1)')  // "bob is paying gas fee"  .setMeta({ chainId: "02", senderAccount: "bob" }): IBuilder;

setNonce

Use setNonce to set IPactCommand.nonce to a custom nonce for the transaction. Otherwise, the nonce is set using the kjs:${timestamp} function.

typescript
Pact.builder.execution(code).setNonce(nonce): IBuilder
typescript
Pact.builder.execution(code).setNonce(nonce): IBuilder
ParameterTypeDescription
noncestringCustom nonce for the transaction.

Examples

typescript
Pact.builder  .execution('(coin.transfer "alice" "bob" 1.1)')  // "bob is paying gas fee"  .setNonce("a-custom-nonce"): IBuilder;
typescript
Pact.builder  .execution('(coin.transfer "alice" "bob" 1.1)')  // "bob is paying gas fee"  .setNonce("a-custom-nonce"): IBuilder;

setNetworkId

Use setNetworkId to set IPactCommand.network to specify the network for the transaction.

typescript
Pact.builder.execution(code).setNetworkId(networkId): IBuilder
typescript
Pact.builder.execution(code).setNetworkId(networkId): IBuilder
ParameterTypeDescription
networkIdstringNetwork identifier, for example, "mainnet01" or "testnet04".

Examples

typescript
Pact.builder  .execution('(coin.transfer "alice" "bob" 1.1)')  // "bob is paying gas fee"  .setNetworkId("testnet04"): IBuilder;
typescript
Pact.builder  .execution('(coin.transfer "alice" "bob" 1.1)')  // "bob is paying gas fee"  .setNetworkId("testnet04"): IBuilder;

createTransaction

use createTransaction to create the transaction object. The createTransaction method adds all of the default values to the command, converts cmd to a string, and adds the hash. You must add signatures to the transaction object using a wallet to submit the transaction to the blockchain. For information about adding signatures from a wallet, see Signing transactions.

typescript
const transaction: IUnsignedCommand = Pact.builder  .execution(code)  .createTransaction(); // : { cmd:"stringified-command" , hash:"command-hash" , sig: [] };
typescript
const transaction: IUnsignedCommand = Pact.builder  .execution(code)  .createTransaction(); // : { cmd:"stringified-command" , hash:"command-hash" , sig: [] };

Examples

typescript
const transaction = Pact.builder  .execution(Pact.modules.coin.transfer(senderAccount, receiverAccount, amount))  .addSigner(senderKey, (signFor) => [    signFor('coin.GAS'),    signFor('coin.TRANSFER', senderAccount, receiverAccount, amount),  ])  .setMeta({ chainId: '0', senderAccount })  .setNetworkId(NETWORK_ID)  .createTransaction(); const output = {  cmd: '{"payload":{"exec":{"code":"(coin.transfer \\"k:dc20ab800b0420be9b1075c97e80b104b073b0405b5e2b78afd29dd74aaf5e46\\" \\"k:2f48080efe54e6eb670487f664bcaac7684b4ebfcfc8a3330ef080c9c97f7e11\\" 1.0)","data":{}}},"nonce":"kjs:nonce:1711376792115","signers":[{"pubKey":"dc20ab800b0420be9b1075c97e80b104b073b0405b5e2b78afd29dd74aaf5e46","scheme":"ED25519","clist":[{"name":"coin.GAS","args":[]},{"name":"coin.TRANSFER","args":["k:dc20ab800b0420be9b1075c97e80b104b073b0405b5e2b78afd29dd74aaf5e46","k:2f48080efe54e6eb670487f664bcaac7684b4ebfcfc8a3330ef080c9c97f7e11",{"decimal":"1"}]}]}],"meta":{"gasLimit":2500,"gasPrice":1e-8,"sender":"k:dc20ab800b0420be9b1075c97e80b104b073b0405b5e2b78afd29dd74aaf5e46","ttl":28800,"creationTime":1711376792,"chainId":"0"},"networkId":"testnet04"}',  hash: 'xYePm_YgO6-T9yIlCZWzOt2s4CkZcQwqWx9Iu5tVSLI',  sigs: [undefined],};
typescript
const transaction = Pact.builder  .execution(Pact.modules.coin.transfer(senderAccount, receiverAccount, amount))  .addSigner(senderKey, (signFor) => [    signFor('coin.GAS'),    signFor('coin.TRANSFER', senderAccount, receiverAccount, amount),  ])  .setMeta({ chainId: '0', senderAccount })  .setNetworkId(NETWORK_ID)  .createTransaction(); const output = {  cmd: '{"payload":{"exec":{"code":"(coin.transfer \\"k:dc20ab800b0420be9b1075c97e80b104b073b0405b5e2b78afd29dd74aaf5e46\\" \\"k:2f48080efe54e6eb670487f664bcaac7684b4ebfcfc8a3330ef080c9c97f7e11\\" 1.0)","data":{}}},"nonce":"kjs:nonce:1711376792115","signers":[{"pubKey":"dc20ab800b0420be9b1075c97e80b104b073b0405b5e2b78afd29dd74aaf5e46","scheme":"ED25519","clist":[{"name":"coin.GAS","args":[]},{"name":"coin.TRANSFER","args":["k:dc20ab800b0420be9b1075c97e80b104b073b0405b5e2b78afd29dd74aaf5e46","k:2f48080efe54e6eb670487f664bcaac7684b4ebfcfc8a3330ef080c9c97f7e11",{"decimal":"1"}]}]}],"meta":{"gasLimit":2500,"gasPrice":1e-8,"sender":"k:dc20ab800b0420be9b1075c97e80b104b073b0405b5e2b78afd29dd74aaf5e46","ttl":28800,"creationTime":1711376792,"chainId":"0"},"networkId":"testnet04"}',  hash: 'xYePm_YgO6-T9yIlCZWzOt2s4CkZcQwqWx9Iu5tVSLI',  sigs: [undefined],};

getCommand

Use getCommand to use the non-stringified version of the command.

typescript
const transaction: IPactCommand = Pact.builder.execution(code).getCommand();
typescript
const transaction: IPactCommand = Pact.builder.execution(code).getCommand();

Examples

typescript
const command = Pact.builder  .execution(Pact.modules.coin.transfer(senderAccount, receiverAccount, amount))  .addSigner(senderKey, (signFor) => [    signFor('coin.GAS'),    signFor('coin.TRANSFER', senderAccount, receiverAccount, amount),  ])  .setMeta({ chainId: '0', senderAccount })  .setNetworkId(NETWORK_ID)  .getCommand(); const output = {  payload: {    exec: {      code: '(coin.transfer "k:dc20ab800b0420be9b1075c97e80b104b073b0405b5e2b78afd29dd74aaf5e46" "k:2f48080efe54e6eb670487f664bcaac7684b4ebfcfc8a3330ef080c9c97f7e11" 1.0)',      data: {},    },  },  nonce: 'kjs:nonce:1711448853909',  signers: [    {      pubKey:        'dc20ab800b0420be9b1075c97e80b104b073b0405b5e2b78afd29dd74aaf5e46',      scheme: 'ED25519',      clist: [        { name: 'coin.GAS', args: [] },        {          name: 'coin.TRANSFER',          args: [            'k:dc20ab800b0420be9b1075c97e80b104b073b0405b5e2b78afd29dd74aaf5e46',            'k:2f48080efe54e6eb670487f664bcaac7684b4ebfcfc8a3330ef080c9c97f7e11',            { decimal: '1' },          ],        },      ],    },  ],  meta: {    gasLimit: 2500,    gasPrice: 1e-8,    sender:      'k:dc20ab800b0420be9b1075c97e80b104b073b0405b5e2b78afd29dd74aaf5e46',    ttl: 28800,    creationTime: 1711448853,    chainId: '0',  },  networkId: 'testnet04',};
typescript
const command = Pact.builder  .execution(Pact.modules.coin.transfer(senderAccount, receiverAccount, amount))  .addSigner(senderKey, (signFor) => [    signFor('coin.GAS'),    signFor('coin.TRANSFER', senderAccount, receiverAccount, amount),  ])  .setMeta({ chainId: '0', senderAccount })  .setNetworkId(NETWORK_ID)  .getCommand(); const output = {  payload: {    exec: {      code: '(coin.transfer "k:dc20ab800b0420be9b1075c97e80b104b073b0405b5e2b78afd29dd74aaf5e46" "k:2f48080efe54e6eb670487f664bcaac7684b4ebfcfc8a3330ef080c9c97f7e11" 1.0)',      data: {},    },  },  nonce: 'kjs:nonce:1711448853909',  signers: [    {      pubKey:        'dc20ab800b0420be9b1075c97e80b104b073b0405b5e2b78afd29dd74aaf5e46',      scheme: 'ED25519',      clist: [        { name: 'coin.GAS', args: [] },        {          name: 'coin.TRANSFER',          args: [            'k:dc20ab800b0420be9b1075c97e80b104b073b0405b5e2b78afd29dd74aaf5e46',            'k:2f48080efe54e6eb670487f664bcaac7684b4ebfcfc8a3330ef080c9c97f7e11',            { decimal: '1' },          ],        },      ],    },  ],  meta: {    gasLimit: 2500,    gasPrice: 1e-8,    sender:      'k:dc20ab800b0420be9b1075c97e80b104b073b0405b5e2b78afd29dd74aaf5e46',    ttl: 28800,    creationTime: 1711448853,    chainId: '0',  },  networkId: 'testnet04',};

initialPactCommand

Use initialPactCommand to set default values for commands you want to reuse in a custom command builder.

ParameterTypeDescription
initialPartialThe initial Pact command values that you want to reuse.
typescript
const builder: ITransactionBuilder =  createTransactionBuilder(initialPactCommand);
typescript
const builder: ITransactionBuilder =  createTransactionBuilder(initialPactCommand);

Examples

To create a transaction builder with network and chain already set:

typescript
// Pre-configure the builderexport const txBuilder = createTransactionBuilder({ networkId: "mainnet01", meta: { chainId: "1" } }); // Then somewhere in the code const command = txBuilder    .execution(Pact.modules.coin.transfer(senderAccount, receiverAccount, amount))    .addSigner(senderKey, (signFor) => [      signFor('coin.GAS'),      signFor('coin.TRANSFER', senderAccount, receiverAccount, amount),    ])    .setMeta({ senderAccount }) const output = const output = {  payload: {    exec: {      code: '(coin.transfer "k:dc20ab800b0420be9b1075c97e80b104b073b0405b5e2b78afd29dd74aaf5e46" "k:2f48080efe54e6eb670487f664bcaac7684b4ebfcfc8a3330ef080c9c97f7e11" 1.0)',      data: {},    },  },  nonce: 'kjs:nonce:1711448853909',  signers: [    {      pubKey:        'dc20ab800b0420be9b1075c97e80b104b073b0405b5e2b78afd29dd74aaf5e46',      scheme: 'ED25519',      clist: [        { name: 'coin.GAS', args: [] },        {          name: 'coin.TRANSFER',          args: [            'k:dc20ab800b0420be9b1075c97e80b104b073b0405b5e2b78afd29dd74aaf5e46',            'k:2f48080efe54e6eb670487f664bcaac7684b4ebfcfc8a3330ef080c9c97f7e11',            { decimal: '1' },          ],        },      ],    },  ],  meta: {    gasLimit: 2500,    gasPrice: 1e-8,    sender:      'k:dc20ab800b0420be9b1075c97e80b104b073b0405b5e2b78afd29dd74aaf5e46',    ttl: 28800,    creationTime: 1711448853,    // Default value    chainId: '1',  },  // Default value  networkId: 'mainnet01',}; 
typescript
// Pre-configure the builderexport const txBuilder = createTransactionBuilder({ networkId: "mainnet01", meta: { chainId: "1" } }); // Then somewhere in the code const command = txBuilder    .execution(Pact.modules.coin.transfer(senderAccount, receiverAccount, amount))    .addSigner(senderKey, (signFor) => [      signFor('coin.GAS'),      signFor('coin.TRANSFER', senderAccount, receiverAccount, amount),    ])    .setMeta({ senderAccount }) const output = const output = {  payload: {    exec: {      code: '(coin.transfer "k:dc20ab800b0420be9b1075c97e80b104b073b0405b5e2b78afd29dd74aaf5e46" "k:2f48080efe54e6eb670487f664bcaac7684b4ebfcfc8a3330ef080c9c97f7e11" 1.0)',      data: {},    },  },  nonce: 'kjs:nonce:1711448853909',  signers: [    {      pubKey:        'dc20ab800b0420be9b1075c97e80b104b073b0405b5e2b78afd29dd74aaf5e46',      scheme: 'ED25519',      clist: [        { name: 'coin.GAS', args: [] },        {          name: 'coin.TRANSFER',          args: [            'k:dc20ab800b0420be9b1075c97e80b104b073b0405b5e2b78afd29dd74aaf5e46',            'k:2f48080efe54e6eb670487f664bcaac7684b4ebfcfc8a3330ef080c9c97f7e11',            { decimal: '1' },          ],        },      ],    },  ],  meta: {    gasLimit: 2500,    gasPrice: 1e-8,    sender:      'k:dc20ab800b0420be9b1075c97e80b104b073b0405b5e2b78afd29dd74aaf5e46',    ttl: 28800,    creationTime: 1711448853,    // Default value    chainId: '1',  },  // Default value  networkId: 'mainnet01',}; 

Signing transactions

After creating the command, you need to sign it using the appropriate secret keys. The signing process is usually managed with a wallet. Kadena has two protocols for signing transactions, each serving different purposes:

  • Sign API: The Sign API allows users to send their sign requests to the wallet. The wallet is then responsible for creating and signing the transaction simultaneously. With this approach, the wallet has more freedom, making it more suitable for simple transactions.

  • Quicksign: The Quicksign API is designed to give applications full control over the command, with the wallet only responsible for adding signatures. This is the recommended method if you are using the command builder from this library.

Wallets typically have their own API for communicating with applications. You can use the API provided by the wallet, or, depending on the wallet, use one of the wallet-specific wrapper functions for convenience.

Sign function interface

The sign function can be used two ways: If you pass a single transaction to the function, it returns the single signed (or partially signed) transaction. If you pass a list of transactions to the function, it returns the list of signed (or partially signed) transactions.

typescript
interface ISignFunction {  (transaction: IUnsignedCommand): Promise<ICommand | IUnsignedCommand>;  (    transactionList: IUnsignedCommand[],  ): Promise<Array<ICommand | IUnsignedCommand>>;}
typescript
interface ISignFunction {  (transaction: IUnsignedCommand): Promise<ICommand | IUnsignedCommand>;  (    transactionList: IUnsignedCommand[],  ): Promise<Array<ICommand | IUnsignedCommand>>;}

Single Transaction

ParameterTypeDescription
txIUnsignedCommandThe transaction to be signed.

List of Transactions

ParameterTypeDescription
tsListIUnsignedCommand[]List of the transactions to be signed.

createSignWithChainweaver

Use createSignWithChainweaver to sign a transaction using Chainweaver. This function uses the quicksign protocol and returns the actual sign function.

typescript
createSignWithChainweaver(options:{ host?: string }): ISignFunction
typescript
createSignWithChainweaver(options:{ host?: string }): ISignFunction
ParameterTypeDescription
option{ host?: string }option including host URL default { host: 'http://127.0.0.1:9467' }

Examples

To sign one transaction using Chainweaver:

typescript
const signWithChainweaver = createSignWithChainweaver(); const transaction = Pact.builder  .execution(Pact.modules.coin.transfer(senderAccount, receiverAccount, amount))  .addSigner(senderKey, (signFor) => [    signFor('coin.GAS'),    signFor('coin.TRANSFER', senderAccount, receiverAccount, amount),  ])  .setMeta({ chainId: '0', senderAccount })  .setNetworkId(NETWORK_ID)  .createTransaction(); const signedTx = signWithChainweaver(transaction);
typescript
const signWithChainweaver = createSignWithChainweaver(); const transaction = Pact.builder  .execution(Pact.modules.coin.transfer(senderAccount, receiverAccount, amount))  .addSigner(senderKey, (signFor) => [    signFor('coin.GAS'),    signFor('coin.TRANSFER', senderAccount, receiverAccount, amount),  ])  .setMeta({ chainId: '0', senderAccount })  .setNetworkId(NETWORK_ID)  .createTransaction(); const signedTx = signWithChainweaver(transaction);

To sign two transactions using Chainweaver:

typescript
const signWithChainweaver = createSignWithChainweaver(); const [txOneSigned, txTwoSigned] = signWithChainweaver([txOne, txTwo]);
typescript
const signWithChainweaver = createSignWithChainweaver(); const [txOneSigned, txTwoSigned] = signWithChainweaver([txOne, txTwo]);

WalletConnect

The WalletConnect protocol and helper functions are based on KIP-017. You must use the WalletConnect protocol .

createWalletConnectSign

Use createWalletConnectSign to create a walletConnect client and session before you use the helper functions to sign transactions. This method returns the sign function using the sign protocol.

The return object might contain different data than what you would pass from the transaction builder because the sign protocol lets the wallet create the transaction.

typescript
createWalletConnectSign(client, session, walletConnectChainId): (transaction: IUnsignedCommand): Promise<ICommand | IUnsignedCommand>
typescript
createWalletConnectSign(client, session, walletConnectChainId): (transaction: IUnsignedCommand): Promise<ICommand | IUnsignedCommand>

| Parameter | Type | Description | | --------- - | ---- | ----------- | | client | Client | The wallet-connect client object. | | session | SessionTypes.Struct | The wallet-connect session object. | | networkId | string | The network identifier, for example, mainnet01 or testnet04. The identifier can include the kadena: prefix, for example, kadena:mainnet01. |

Examples

typescript
const signWithWalletConnect = createWalletConnectSign(  client,  session,  'mainnet01',); const signedTx = signWithWalletConnect(tx);
typescript
const signWithWalletConnect = createWalletConnectSign(  client,  session,  'mainnet01',); const signedTx = signWithWalletConnect(tx);

createWalletConnectQuicksign

Use createWalletConnectQuicksign to sign a transaction and return the sign function using thequicksign protocol.

typescript
createWalletConnectQuicksign(client, session, walletConnectChainId): ISignFunction
typescript
createWalletConnectQuicksign(client, session, walletConnectChainId): ISignFunction
ParameterTypeDescription
clientClientThe wallet-connect client object.
sessionSessionTypes.StructThe wallet-connect session object.
networkIdstringThe network identifier, for example, mainnet01 or testnet04. The identifier can include the kadena: prefix, for example, kadena:mainnet01.

Examples

typescript
const quicksignWithWalletConnect = createWalletConnectQuicksign(  client,  session,  'mainnet01',); const signedTx = quicksignWithWalletConnect(tx);
typescript
const quicksignWithWalletConnect = createWalletConnectQuicksign(  client,  session,  'mainnet01',); const signedTx = quicksignWithWalletConnect(tx);

EckoWallet

The following functions provide the sign and quicksign protocols for EckoWallet to return a sign function and other properties:

typescript
const { isInstalled, isConnected, connect } = createEckoWalletSign();const { isInstalled, isConnected, connect } = createEckoWalletQuicksign();
typescript
const { isInstalled, isConnected, connect } = createEckoWalletSign();const { isInstalled, isConnected, connect } = createEckoWalletQuicksign();

isInstalled

You can use isInstalled to check if the EckoWallet extension is installed in the browser.

typescript
isInstalled(): boolean
typescript
isInstalled(): boolean

isConnected

You can use isConnected to check if the application is already connected to EckoWallet.

typescript
isConnected(): Promise<boolean>
typescript
isConnected(): Promise<boolean>

connect

You can use connect to send a connection request to EckoWallet.

typescript
connect(networkId: string): Promise<boolean>
typescript
connect(networkId: string): Promise<boolean>

createEckoWalletSign

The createEckoWalletSign function uses the sign protocol to communicate with EckoWallet. The return object might contain different data than what you would pass from the transaction builder because the sign protocol lets the wallet create the transaction.

typescript
createEckoWalletSign(options:{ host?: string }): (transaction: IUnsignedCommand): Promise<ICommand | IUnsignedCommand>
typescript
createEckoWalletSign(options:{ host?: string }): (transaction: IUnsignedCommand): Promise<ICommand | IUnsignedCommand>

Examples

To sign a transaction using EckoWallet:

typescript
const signWithEckoWallet = createEckoWalletSign(); // the wallet will create the completed oneconst partialTx = Pact.builder  .execution(Pact.modules.coin.transfer(senderAccount, receiverAccount, amount))  .addSigner(senderKey, (signFor) => [    signFor('coin.GAS'),    signFor('coin.TRANSFER', senderAccount, receiverAccount, amount),  ])  .setMeta({ chainId: '0' })  .setNetworkId(NETWORK_ID)  .createTransaction(); const signedTx = signWithEckoWallet(partialTx);
typescript
const signWithEckoWallet = createEckoWalletSign(); // the wallet will create the completed oneconst partialTx = Pact.builder  .execution(Pact.modules.coin.transfer(senderAccount, receiverAccount, amount))  .addSigner(senderKey, (signFor) => [    signFor('coin.GAS'),    signFor('coin.TRANSFER', senderAccount, receiverAccount, amount),  ])  .setMeta({ chainId: '0' })  .setNetworkId(NETWORK_ID)  .createTransaction(); const signedTx = signWithEckoWallet(partialTx);

createEckoWalletQuicksign

The createEckoWalletQuicksign function uses the quicksign protocol to communicate with EckoWallet.

typescript
createEckoWalletQuicksign(options:{ host?: string }): ISignFunction
typescript
createEckoWalletQuicksign(options:{ host?: string }): ISignFunction

Examples

To sign one transaction using the quicksign protocol and EckoWallet:

typescript
const quicksignWithEckoWallet = createEckoWalletQuicksign(); const tx = Pact.builder  .execution(Pact.modules.coin.transfer(senderAccount, receiverAccount, amount))  .addSigner(senderKey, (signFor) => [    signFor('coin.GAS'),    signFor('coin.TRANSFER', senderAccount, receiverAccount, amount),  ])  .setMeta({ chainId: '0', senderAccount })  .setNetworkId(NETWORK_ID)  .createTransaction(); const signedTx = quicksignWithEckoWallet(partialTx);
typescript
const quicksignWithEckoWallet = createEckoWalletQuicksign(); const tx = Pact.builder  .execution(Pact.modules.coin.transfer(senderAccount, receiverAccount, amount))  .addSigner(senderKey, (signFor) => [    signFor('coin.GAS'),    signFor('coin.TRANSFER', senderAccount, receiverAccount, amount),  ])  .setMeta({ chainId: '0', senderAccount })  .setNetworkId(NETWORK_ID)  .createTransaction(); const signedTx = quicksignWithEckoWallet(partialTx);

To sign two transactions using the quicksign protocol and EckoWallet:

typescript
const quicksignWithEckoWallet = createEckoWalletQuicksign(); const [txOneSigned, txTwoSigned] = quicksignWithEckoWallet([txOne, txTwo]);
typescript
const quicksignWithEckoWallet = createEckoWalletQuicksign(); const [txOneSigned, txTwoSigned] = quicksignWithEckoWallet([txOne, txTwo]);

createSignWithKeypair

Use createSignWithKeypair to sign transactions using a secret key in a safe environment such as a server environment or CI test pipeline and return the sign function.

The IKeyPair interface is defined as follows:

typescript
interface IKeyPair {  publicKey: string;  secretKey: string;}
typescript
interface IKeyPair {  publicKey: string;  secretKey: string;}
typescript
createSignWithKeypair(keyOrKeys:IKeyPair | IKeyPair[]): ISignFunction
typescript
createSignWithKeypair(keyOrKeys:IKeyPair | IKeyPair[]): ISignFunction

Examples

To sign with one key pair:

typescript
const signWithKeypair = createSignWithKeypair({ publicKey, secretKey }); const signedTx = signWithKeypair(tx);
typescript
const signWithKeypair = createSignWithKeypair({ publicKey, secretKey }); const signedTx = signWithKeypair(tx);

To sign with several key pairs:

typescript
const signWithKeypair = createSignWithKeypair([firstKeyPair, secondKeyPair]); const signedTx = signWithKeypair(tx);
typescript
const signWithKeypair = createSignWithKeypair([firstKeyPair, secondKeyPair]); const signedTx = signWithKeypair(tx);

addSignatures

Use addSignatures to add one or more signatures you have to the transaction.

All signatures you add should either include a public key, or none of them should. If the signatures don't include the public keys, then the number of signatures must match the number of signers, and the signatures are matched based on their order.

typescript
addSignatures(transaction, ...signatures): IUnsignedCommand | ICommand
typescript
addSignatures(transaction, ...signatures): IUnsignedCommand | ICommand
ParameterTypeDescription
transactionIUnsignedCommandThe partially signed or unsigned transaction.
...signaturesArray<{ sig: string; pubKey: string }>Array<{ sig: string }>

Examples

To add a signature manually with a public key:

typescript
const signedTx = addSignatures(partiallySignedTx, {  sig: 'signature-str',  pubKey: 'publicKey',});
typescript
const signedTx = addSignatures(partiallySignedTx, {  sig: 'signature-str',  pubKey: 'publicKey',});

To add a signature based on the signer order:

typescript
const signedTx = addSignatures(  twoSignersTx,  { sigOne: 'signature-str' },  { sigTwo: 'signature-str' },);
typescript
const signedTx = addSignatures(  twoSignersTx,  { sigOne: 'signature-str' },  { sigTwo: 'signature-str' },);

createClient

Use createClient to return the IClient interface for communicating with Chainweb nodes.

TS
createClient(  host?: string | (options: {chainId: ChainId; networkId: string}) => string,  options?: { confirmationDepth?: number }): IClientinterface IClient {  getStatus: (transactionDescriptors: ITransactionDescriptor[] | ITransactionDescriptor) => Promise<IPollResponse>;  submit: {    (transaction: ICommand): Promise<ITransactionDescriptor>;    (transactionList: ICommand[]): Promise<ITransactionDescriptor[]>;  }  send: {    (transaction: ICommand): Promise<ITransactionDescriptor>;    (transactionList: ICommand[]): Promise<ITransactionDescriptor[]>;  }  submitOne: (transaction: ICommand) => Promise<ITransactionDescriptor>;  listen: (transactionDescriptor: ITransactionDescriptor) => Promise<ICommandResult>;  pollOne: (transactionDescriptor: ITransactionDescriptor) => Promise<ICommandResult>;  pollStatus: (transactionDescriptors: ITransactionDescriptor[] | ITransactionDescriptor, options?: IPollOptions) => IPollRequestPromise<ICommandResult>;  getPoll: (transactionDescriptors: ITransactionDescriptor[] | ITransactionDescriptor) => Promise<IPollResponse>;  local: <T extends ILocalOptions>(transaction: LocalRequestBody, options?: T) => Promise<LocalResponse<T>>;  dirtyRead: (transaction: IUnsignedCommand) => Promise<ICommandResult>;  preflight: (transaction: ICommand | IUnsignedCommand) => Promise<ILocalCommandResult>;  signatureVerification: (transaction: ICommand) => Promise<ICommandResult>;  runPact: (code: string, data: Record<string, unknown>, option: INetworkOptions) => Promise<ICommandResult>;  createSpv: (transactionDescriptor: ITransactionDescriptor, targetChainId: ChainId) => Promise<string>;  pollCreateSpv: (transactionDescriptor: ITransactionDescriptor, targetChainId: ChainId, options?: IPollOptions) => Promise<string>;}
TS
createClient(  host?: string | (options: {chainId: ChainId; networkId: string}) => string,  options?: { confirmationDepth?: number }): IClientinterface IClient {  getStatus: (transactionDescriptors: ITransactionDescriptor[] | ITransactionDescriptor) => Promise<IPollResponse>;  submit: {    (transaction: ICommand): Promise<ITransactionDescriptor>;    (transactionList: ICommand[]): Promise<ITransactionDescriptor[]>;  }  send: {    (transaction: ICommand): Promise<ITransactionDescriptor>;    (transactionList: ICommand[]): Promise<ITransactionDescriptor[]>;  }  submitOne: (transaction: ICommand) => Promise<ITransactionDescriptor>;  listen: (transactionDescriptor: ITransactionDescriptor) => Promise<ICommandResult>;  pollOne: (transactionDescriptor: ITransactionDescriptor) => Promise<ICommandResult>;  pollStatus: (transactionDescriptors: ITransactionDescriptor[] | ITransactionDescriptor, options?: IPollOptions) => IPollRequestPromise<ICommandResult>;  getPoll: (transactionDescriptors: ITransactionDescriptor[] | ITransactionDescriptor) => Promise<IPollResponse>;  local: <T extends ILocalOptions>(transaction: LocalRequestBody, options?: T) => Promise<LocalResponse<T>>;  dirtyRead: (transaction: IUnsignedCommand) => Promise<ICommandResult>;  preflight: (transaction: ICommand | IUnsignedCommand) => Promise<ILocalCommandResult>;  signatureVerification: (transaction: ICommand) => Promise<ICommandResult>;  runPact: (code: string, data: Record<string, unknown>, option: INetworkOptions) => Promise<ICommandResult>;  createSpv: (transactionDescriptor: ITransactionDescriptor, targetChainId: ChainId) => Promise<string>;  pollCreateSpv: (transactionDescriptor: ITransactionDescriptor, targetChainId: ChainId, options?: IPollOptions) => Promise<string>;}

You can use object destructuring to extract specific functions. For example:

TS
const { submit, local, pollCreateSpv } = createClient();
TS
const { submit, local, pollCreateSpv } = createClient();
ParameterTypeDescription
hoststring(options: {chainId: ChainId; networkId: string}) => string
options{ confirmationDepth?: number }Additional options for the client. It has only one property now: confirmationDepth, which can be used in the poll endpoint. Default value is 0.

Both host and options are optional arguments. The default value of host is a URL generator function that returns the Chainweb node URLs for mainnet and testnet. If you want to use different URLs, you must specify the host parameter.

The networkId and chainId parameters are read from the command object and passed to the URL generator function.

Examples

To create a client for the development network and a specific chain identifier (1):

TS
const client = createClient("http://127.0.0.1:8080/chainweb/0.0/development/chain/1/pact");
TS
const client = createClient("http://127.0.0.1:8080/chainweb/0.0/development/chain/1/pact");

To create a client for the development network that covers multi-chain and uses the URL generator function for more flexibility:

TS
const devNetClient = createClient(({chainId, networkId})=>   `http://127.0.0.1:8080/chainweb/0.0/${networkId}/chain/${chainId ?? '1'}/pact`);
TS
const devNetClient = createClient(({chainId, networkId})=>   `http://127.0.0.1:8080/chainweb/0.0/${networkId}/chain/${chainId ?? '1'}/pact`);

To create a client that uses mainnet but not Kadena main network nodes:

TS
const client = createClient(({ chainId, networkId }) => {  switch (networkId) {    case 'mainnet01':      return `http://my-node-url/chainweb/0.0/${networkId}/chain/{${chainId}}/pact`;    case 'testnet04':      return `http://my-test-node-url/chainweb/0.0/${networkId}/chain/{${chainId}}/pact`;    default:      throw new Error('UNKNOWN_NETWORK');  }});
TS
const client = createClient(({ chainId, networkId }) => {  switch (networkId) {    case 'mainnet01':      return `http://my-node-url/chainweb/0.0/${networkId}/chain/{${chainId}}/pact`;    case 'testnet04':      return `http://my-test-node-url/chainweb/0.0/${networkId}/chain/{${chainId}}/pact`;    default:      throw new Error('UNKNOWN_NETWORK');  }});

To create a client with a confirmationDepth of 5 that waits for five new blocks to be added to the chain before reading the result of a transaction:

TS
const { submit, pollStatus } = createClient(undefined, { confirmationDepth: 5 });
TS
const { submit, pollStatus } = createClient(undefined, { confirmationDepth: 5 });

submit

Use submit to submit one transaction or a list of transactions to the blockchain.

To send a single transaction:

TS
const { submit } = createClient();submit(tx): Promise<ITransactionDescriptor>;interface ITransactionDescriptor {  networkId: string;  chainId: ChainId;  requestKey: string}
TS
const { submit } = createClient();submit(tx): Promise<ITransactionDescriptor>;interface ITransactionDescriptor {  networkId: string;  chainId: ChainId;  requestKey: string}
ParameterTypeDescription
txICommandThe command object ready to submit.

To submit a list of transactions:

TS
const { submit } = createClient();submit(txList): Promise<ITransactionDescriptor[]>;
TS
const { submit } = createClient();submit(txList): Promise<ITransactionDescriptor[]>;
ParameterTypeDescription
txListICommand[]List of command objects ready to submit.

In most cases, you should store the result of this function so you can fetch the result of the request.

The submitOne function is the same as submitting one transaction using the submit function. For example:

TS
const { submitOne } = createClient();submitOne(tx): Promise<ITransactionDescriptor>;
TS
const { submitOne } = createClient();submitOne(tx): Promise<ITransactionDescriptor>;
ParameterTypeDescription
txICommandThe command object ready to submit.

getStatus

Use getStatus to call the /poll endpoint and return the result of requests.

TS
const { getStatus } = createClient();getStatus(transactionDescriptor: TransactionDescriptor[] | ITransactionDescriptor): Promise<{    [requestKey: IBase64Url]: { [requestKey:string] ICommandResult};}>
TS
const { getStatus } = createClient();getStatus(transactionDescriptor: TransactionDescriptor[] | ITransactionDescriptor): Promise<{    [requestKey: IBase64Url]: { [requestKey:string] ICommandResult};}>

Parameters

ParameterTypeDescription
transactionDescriptorTransactionDescriptorTransactionDescriptor[]

Return value

ICommandResult interface:

TS
interface ICommandResult {  reqKey: string;  txId: number | null;  result:    | {        status: 'success';        data: PactValue;      }    | {        status: 'failure';        error: object;      };  gas: number;  logs: string | null;  // for defpact functions  continuation: null | {    pactId: PactTransactionHash;    step: Step;    stepCount: number;    executed: boolean | null;    stepHasRollback: boolean;    continuation: {      def: string;      args: PactValue;    };    yield: {      data: Array<[string, PactValue]>;      provenance: {          targetChainId: ChainId;          moduleHash: string;      } | null;    };  };  metaData: null | {    blockHash: string;    blockTime: number;    blockHeight: number;    prevBlockHash: string;    publicMeta?: IPactCommand['meta']  };  events: Array<{    name: string;    module: {      name: string;      namespace: string | null;    };    params: Array<PactValue>;    moduleHash: string;  }>;}
TS
interface ICommandResult {  reqKey: string;  txId: number | null;  result:    | {        status: 'success';        data: PactValue;      }    | {        status: 'failure';        error: object;      };  gas: number;  logs: string | null;  // for defpact functions  continuation: null | {    pactId: PactTransactionHash;    step: Step;    stepCount: number;    executed: boolean | null;    stepHasRollback: boolean;    continuation: {      def: string;      args: PactValue;    };    yield: {      data: Array<[string, PactValue]>;      provenance: {          targetChainId: ChainId;          moduleHash: string;      } | null;    };  };  metaData: null | {    blockHash: string;    blockTime: number;    blockHeight: number;    prevBlockHash: string;    publicMeta?: IPactCommand['meta']  };  events: Array<{    name: string;    module: {      name: string;      namespace: string | null;    };    params: Array<PactValue>;    moduleHash: string;  }>;}

pollStatus

Use pollStatus to call the /poll endpoint in intervals and return the result of all requests when all are ready.

TS
const { pollStatus } = createClient();pollStatus(  transactionDescriptor: TransactionDescriptor[] | ITransactionDescriptor,  pollOptions: {    onPoll?: (id: string) => void;    timeout?: Milliseconds;    interval?: Milliseconds;    confirmationDepth?: number;  }): IPollRequestPromise<{    [requestKey: IBase64Url]: { [requestKey:string] ICommandResult};}>interface IPollRequestPromise extends Promise {  [requestKey: IBase64Url]: Promise<ICommandResult>}
TS
const { pollStatus } = createClient();pollStatus(  transactionDescriptor: TransactionDescriptor[] | ITransactionDescriptor,  pollOptions: {    onPoll?: (id: string) => void;    timeout?: Milliseconds;    interval?: Milliseconds;    confirmationDepth?: number;  }): IPollRequestPromise<{    [requestKey: IBase64Url]: { [requestKey:string] ICommandResult};}>interface IPollRequestPromise extends Promise {  [requestKey: IBase64Url]: Promise<ICommandResult>}

Parameters

ParameterTypeDescription
transactionDescriptorTransactionDescriptorTransactionDescriptor[]
pollOptions{ onPoll?: (id: string) => void; timeout?: Milliseconds; interval?: Milliseconds; confirmationDepth?: number; }onPoll: Callback is called when the request is polling; this might be called several times if the request is not ready yet. Timeout: Timeout if the result is not ready (default 180000 // 3 minutes). Interval: Delay between retries (default is 5000 // 5 seconds). ConfirmationDepth: Set the confirmationDepth for getting the response; this overrides the one you set in createClient function

Return value

The return value is a special type of promise. Though you can just await for the result just like a normal promise - which is the case for most of the typical use cases - you can still listen for each individual request via the requests property.

Examples

Poll the status of a request:

TS
const result = await pollStatus(request, {});
TS
const result = await pollStatus(request, {});

Poll the status of several requests and get the result for each one immediately:

TS
const resultPromise = pollStatus([firstRequest, secondRequest, thirdRequest]);// Notify the UI from the result of each request as soon as it's availableresultPromise.requests["first-request-key"].then(res => {UI.notify(res)});resultPromise.requests["second-request-key"].then(res => {UI.notify(res)});resultPromise.requests["third-request-key"].then(res => {UI.notify(res)});// The final result objectconst finalResult = await resultPromise;
TS
const resultPromise = pollStatus([firstRequest, secondRequest, thirdRequest]);// Notify the UI from the result of each request as soon as it's availableresultPromise.requests["first-request-key"].then(res => {UI.notify(res)});resultPromise.requests["second-request-key"].then(res => {UI.notify(res)});resultPromise.requests["third-request-key"].then(res => {UI.notify(res)});// The final result objectconst finalResult = await resultPromise;

listen

Use listen to call the /listen endpoint, which is a blocking endpoint. If your network or firewall configuration doesn't allow keeping HTTP connections open for a long time, then it's better to use pollOne which has the same interface but uses /poll under the hood.

TS
const { listen } = createClient();listen(transactionDescriptor: TransactionDescriptor[] | ITransactionDescriptor): Promise<ICommandResult>
TS
const { listen } = createClient();listen(transactionDescriptor: TransactionDescriptor[] | ITransactionDescriptor): Promise<ICommandResult>
ParameterTypeDescription
transactionDescriptorTransactionDescriptorThe request object including requestKet, networkId, chainId

pollOne

Use pollOne to call the /poll endpoint to return the result of only one request.

TS
const { pollOne } = createClient();pollOne(transactionDescriptor: TransactionDescriptor[] | ITransactionDescriptor): Promise<ICommandResult>
TS
const { pollOne } = createClient();pollOne(transactionDescriptor: TransactionDescriptor[] | ITransactionDescriptor): Promise<ICommandResult>

Parameters

ParameterTypeDescription
transactionDescriptorTransactionDescriptorThe request object including requestKet, networkId, chainId

local

Use local to call the /local endpoint.

TS
local(  transaction: ICommand | IUnsignedCommand,  options?: { preflight?: boolean; signatureVerification?: boolean; }): Promise<ICommandResult & { preflightWarnings?: string[] }>;
TS
local(  transaction: ICommand | IUnsignedCommand,  options?: { preflight?: boolean; signatureVerification?: boolean; }): Promise<ICommandResult & { preflightWarnings?: string[] }>;

The return type is ICommandResult with preflightWarnings when it is set to true.

ParameterTypeDescription
transactionICommandIUnsignedCommand
option{ preflight?: boolean; signatureVerification?: boolean; }preflight: Runs the code in the preflight mode which simulates submitting the transaction so you can also have the gas consumption result (default = true). SignatureVerification: Run the signature verification in the node as well; then the transaction should have the transactions as well (default = true).

Examples

To avoid submitting an incorrect transaction:

TS
// Check if the transaction and signatures are correctconst response = await client.local(signedTx);if (response.result.status === 'failure') {  // Throw if the transaction fails to avoid paying gas for a failed transaction  throw response.result.error;}const request = await client.submit(signedTx);
TS
// Check if the transaction and signatures are correctconst response = await client.local(signedTx);if (response.result.status === 'failure') {  // Throw if the transaction fails to avoid paying gas for a failed transaction  throw response.result.error;}const request = await client.submit(signedTx);

To simulate a transaction for gas estimation:

TS
// We don't need to send signatures to check gas estimation;const response = await client.local(unsignedTx, { preflight:true , signatureVerification: false });if (response.result.status === 'failure') {  throw response.result.error;}const gasEstimation =  response.gas;
TS
// We don't need to send signatures to check gas estimation;const response = await client.local(unsignedTx, { preflight:true , signatureVerification: false });if (response.result.status === 'failure') {  throw response.result.error;}const gasEstimation =  response.gas;

dirtyRead

Use dirtyRead to read data from a node without submitting a transaction to the blockchain.

TS
dirtyRead(transaction: ICommand | IUnsignedCommand): Promise<ICommandResult>;
TS
dirtyRead(transaction: ICommand | IUnsignedCommand): Promise<ICommandResult>;

Parameters

ParameterTypeDescription
transactionICommandIUnsignedCommand

Examples

To get an account balance:

TS
const tr = Pact.builder  .execution(Pact.modules.coin['get-balance'](account))  .setMeta({ chainId: '0' })  .setNetworkId("mainnet04")  .createTransaction();// We don't need to submit a transaction for just reading data,// so instead we just read the value from the local data of the blockchain nodeconst res = await dirtyRead(tr);if (res.result.status === 'failure') {  throw res.result.error;}const balance = res.result.data;
TS
const tr = Pact.builder  .execution(Pact.modules.coin['get-balance'](account))  .setMeta({ chainId: '0' })  .setNetworkId("mainnet04")  .createTransaction();// We don't need to submit a transaction for just reading data,// so instead we just read the value from the local data of the blockchain nodeconst res = await dirtyRead(tr);if (res.result.status === 'failure') {  throw res.result.error;}const balance = res.result.data;

preflight

Use preflight to call the /local endpoint with the preflight value set to true, but signatureVerification value set to false.

TS
preflight(transaction: ICommand | IUnsignedCommand): Promise<ICommandResult>;
TS
preflight(transaction: ICommand | IUnsignedCommand): Promise<ICommandResult>;

Parameters

ParameterTypeDescription
transactionICommandIUnsignedCommand

signatureVerification

Use signatureVerification to call the /local endpoint with the signatureVerification value set to true, but preflight value set to false.

TS
signatureVerification(transaction: ICommand | IUnsignedCommand): Promise<ICommandResult & { preflightWarnings?: string[] }>;
TS
signatureVerification(transaction: ICommand | IUnsignedCommand): Promise<ICommandResult & { preflightWarnings?: string[] }>;

Parameters

ParameterTypeDescription
transactionICommandIUnsignedCommand

runPact

If you just want to see the result of a pact code and don't want to create a command object, you can use the runPact function. This function creates a command object internally.

TS
runPact(code: string, data?: Record<string, unknown>, options?: { chainId: ChainId; networkId: string }): Promise<ICommandResult>;
TS
runPact(code: string, data?: Record<string, unknown>, options?: { chainId: ChainId; networkId: string }): Promise<ICommandResult>;

Parameters

ParameterTypeDescription
codestringPact code.
dataRecord<string, unknown>Data to be sent with the transaction.
options{ chainId: ChainId; networkId: string }ChainId and networkId that you want to send the transaction to.

Examples

TS
const { runPact } = createClient()const result = await runPact(`(coin.getBalance "alice")`, { }, { networkId:"mainnet01", chainId:"1" })
TS
const { runPact } = createClient()const result = await runPact(`(coin.getBalance "alice")`, { }, { networkId:"mainnet01", chainId:"1" })

createSPV

Use createSPV to call the /spv endpoint to request a simple payment verification proof if it's ready.

TS
createSpv(transactionDescriptor: ITransactionDescriptor, targetChainId: ChainId): Promise<string>;
TS
createSpv(transactionDescriptor: ITransactionDescriptor, targetChainId: ChainId): Promise<string>;

Parameters

ParameterTypeDescription
transactionDescriptor{ requestKey: string; networkId: string; chainId: ChainId }The transaction for which you want to create an SPV proof.
targetChainIdChainIdThe chain that consumes this proof.

pollCreateSPV

Use pollCreateSPV to poll the /spv endpoint for a simple payment verification proof until the proof is ready.

TS
pollCreateSpv(  transactionDescriptor: ITransactionDescriptor,  targetChainId: ChainId,  pollOptions?: { onPoll?: (id: string) => void; timeout?: Milliseconds; interval?: Milliseconds; }): Promise<string>;
TS
pollCreateSpv(  transactionDescriptor: ITransactionDescriptor,  targetChainId: ChainId,  pollOptions?: { onPoll?: (id: string) => void; timeout?: Milliseconds; interval?: Milliseconds; }): Promise<string>;

Parameters

ParameterTypeDescription
transactionDescriptor{ requestKey: string; networkId: string; chainId: ChainId }The transaction for which you want to create an SPV proof.
targetChainIdChainIdThe chain that consumes this proof.
pollOptions{ onPoll?: (id: string) => void; timeout?: Milliseconds; interval?: Milliseconds; }onPoll: Callback is called when the request is polling; this might be called several times if the request is not ready yet. Timeout: Timeout if the result is not ready (default 180000 // 3 minutes). Interval: Delay between retries (default is 5000 // 5 seconds)

Examples

TS
const request = await submit(crossChainTx)const response = await pollOne(request)// create spv proof for the transactionconst spvProof = await pollSpvProof(request)const continuationTx = Pact.builder.continuation({  pactId: response.continuation.pactId,  rollback: false,  step:1,  proof: spvProof}).addMeta({  chainId: targetChainId,  // using gas station for paying gas fee  senderAccount : 'kadena-xchain-gas'}).createTransaction()const contRequest = await submit(continuationTx)const finalResult = await pollOne(contRequest)
TS
const request = await submit(crossChainTx)const response = await pollOne(request)// create spv proof for the transactionconst spvProof = await pollSpvProof(request)const continuationTx = Pact.builder.continuation({  pactId: response.continuation.pactId,  rollback: false,  step:1,  proof: spvProof}).addMeta({  chainId: targetChainId,  // using gas station for paying gas fee  senderAccount : 'kadena-xchain-gas'}).createTransaction()const contRequest = await submit(continuationTx)const finalResult = await pollOne(contRequest)

composePactCommand

Use composePactCommand to use the functional programming API to compose parts of a Pact command and create the final command object.

typescript
type CommandReducer = (cmd?: IPartialPactCommand | (() => IPartialPactCommand)) => IPartialPactCommand; composePactCommand(  ...reducersOrPartialCommands: Array<IPartialPactCommand | CommandReducer>  ): CommandReducer
typescript
type CommandReducer = (cmd?: IPartialPactCommand | (() => IPartialPactCommand)) => IPartialPactCommand; composePactCommand(  ...reducersOrPartialCommands: Array<IPartialPactCommand | CommandReducer>  ): CommandReducer

Parameters

ParameterTypeDescription
...reducersOrPartialCommandsArray<IPartialPactCommandCommandReducer>

Return value

The return value is a CommandReducer function that you can pass to another composePactCommand. Eventually, when you call the function, it also adds the default values.

Examples

typescript
const pactCommand = composePactCommand(  { payload: { exec: { code: '(+ 1 1)' } } },  (cmd) => ({ ...cmd, meta: { chainId: '1' } }),  { networkId: 'testnet04' },)(); const pactCommand = {  payload: { exec: { code: '(+ 1 1)' } },  meta: {    gasLimit: 2500,    gasPrice: 1e-8,    sender: '',    ttl: 28800,    creationTime: 1690416000,    chainId: '1',  },  networkId: 'testnet04',  nonce: 'kjs:nonce:1690416000000',  signers: [],};
typescript
const pactCommand = composePactCommand(  { payload: { exec: { code: '(+ 1 1)' } } },  (cmd) => ({ ...cmd, meta: { chainId: '1' } }),  { networkId: 'testnet04' },)(); const pactCommand = {  payload: { exec: { code: '(+ 1 1)' } },  meta: {    gasLimit: 2500,    gasPrice: 1e-8,    sender: '',    ttl: 28800,    creationTime: 1690416000,    chainId: '1',  },  networkId: 'testnet04',  nonce: 'kjs:nonce:1690416000000',  signers: [],};

Supported functions

You can use the following functions with composePactCommand:

  • execution
  • continuation
  • addSigner
  • addData
  • addKeyset
  • setMeta
  • setNonce
  • setNetworkId
  • createTransaction

Examples

The following examples illustrate using composePactCommand in different scenarios.

Create an execution command using Pact.modules:

typescript
const command: IPactCommand = composePactCommand(  execution(Pact.modules.coin.transfer('alice', 'bob', { decimal: '1.1' })),)();
typescript
const command: IPactCommand = composePactCommand(  execution(Pact.modules.coin.transfer('alice', 'bob', { decimal: '1.1' })),)();

Create a continuation command:

TS
const command: IPactCommand = composePactCommand(  continuation({    pactId,    rollback: false,    step:1,    proof: spvProof  }))()
TS
const command: IPactCommand = composePactCommand(  continuation({    pactId,    rollback: false,    step:1,    proof: spvProof  }))()

Add a signer with a key that uses the WebAuthn signature scheme:

typescript
composePactCommand(  execution(Pact.modules.coin.transfer('alice', 'bob', { decimal: '1.1' })),  addSigner({ pubKey: webAuthnPublicKey, scheme: 'WebAuthn' }, (signFor) => [    signFor('coin.TRANSFER', 'alice', 'bob', { decimal: '1.1' }),  ]),);
typescript
composePactCommand(  execution(Pact.modules.coin.transfer('alice', 'bob', { decimal: '1.1' })),  addSigner({ pubKey: webAuthnPublicKey, scheme: 'WebAuthn' }, (signFor) => [    signFor('coin.TRANSFER', 'alice', 'bob', { decimal: '1.1' }),  ]),);

Add sender and receiver data to a transfer operation:

typescript
composePactCommand(  execution(    '(coin.transfer (read-string "sender") (read-string "receiver") 1.1)',  ),  addData('sender', sender),  addData('receiver', sender),);
typescript
composePactCommand(  execution(    '(coin.transfer (read-string "sender") (read-string "receiver") 1.1)',  ),  addData('sender', sender),  addData('receiver', sender),);

Add a keyset for a transfer and create operation:

typescript
composePactCommand(  execution(    Pact.modules.coin['transfer-create'](      'alice',      'bob',      readKeyset('bob-guard'),      { decimal: '1.1' },    ),  ),  addKeyset('bob-guard', 'keys-all', 'bob-public-key'),);
typescript
composePactCommand(  execution(    Pact.modules.coin['transfer-create'](      'alice',      'bob',      readKeyset('bob-guard'),      { decimal: '1.1' },    ),  ),  addKeyset('bob-guard', 'keys-all', 'bob-public-key'),);

Set metadata for a transfer operation:

typescript
composePactCommand(  execution('(coin.transfer "alice" "bob" 1.1)'),  // "bob is paying gas fee"  setMeta({ chainId: '02', senderAccount: 'bob' }),);
typescript
composePactCommand(  execution('(coin.transfer "alice" "bob" 1.1)'),  // "bob is paying gas fee"  setMeta({ chainId: '02', senderAccount: 'bob' }),);

Set a custom nonce:

typescript
composePactCommand(  execution('(coin.transfer "alice" "bob" 1.1)'),  // "bob is paying gas fee"  setNonce('a-custom-nonce'),);
typescript
composePactCommand(  execution('(coin.transfer "alice" "bob" 1.1)'),  // "bob is paying gas fee"  setNonce('a-custom-nonce'),);

Set the network identifier for the transaction

typescript
composePactCommand(  execution('(coin.transfer "alice" "bob" 1.1)'),  // "bob is paying gas fee"  setNetworkId('testnet04'),);
typescript
composePactCommand(  execution('(coin.transfer "alice" "bob" 1.1)'),  // "bob is paying gas fee"  setNetworkId('testnet04'),);

Create the transaction object to be signed:

typescript
const pactCommand = composePactCommand(  execution(Pact.modules.coin.transfer(senderAccount, receiverAccount, amount)),  addSigner(senderKey, (signFor) => [    signFor('coin.GAS'),    signFor('coin.TRANSFER', senderAccount, receiverAccount, amount),  ]),  setMeta({ chainId: '0', senderAccount }),  setNetworkId(NETWORK_ID),  createTransaction(),); const transaction = createTransaction(pactCommand); const output = {  cmd: '{"payload":{"exec":{"code":"(coin.transfer \\"k:dc20ab800b0420be9b1075c97e80b104b073b0405b5e2b78afd29dd74aaf5e46\\" \\"k:2f48080efe54e6eb670487f664bcaac7684b4ebfcfc8a3330ef080c9c97f7e11\\" 1.0)","data":{}}},"nonce":"kjs:nonce:1711376792115","signers":[{"pubKey":"dc20ab800b0420be9b1075c97e80b104b073b0405b5e2b78afd29dd74aaf5e46","scheme":"ED25519","clist":[{"name":"coin.GAS","args":[]},{"name":"coin.TRANSFER","args":["k:dc20ab800b0420be9b1075c97e80b104b073b0405b5e2b78afd29dd74aaf5e46","k:2f48080efe54e6eb670487f664bcaac7684b4ebfcfc8a3330ef080c9c97f7e11",{"decimal":"1"}]}]}],"meta":{"gasLimit":2500,"gasPrice":1e-8,"sender":"k:dc20ab800b0420be9b1075c97e80b104b073b0405b5e2b78afd29dd74aaf5e46","ttl":28800,"creationTime":1711376792,"chainId":"0"},"networkId":"testnet04"}',  hash: 'xYePm_YgO6-T9yIlCZWzOt2s4CkZcQwqWx9Iu5tVSLI',  sigs: [undefined],};
typescript
const pactCommand = composePactCommand(  execution(Pact.modules.coin.transfer(senderAccount, receiverAccount, amount)),  addSigner(senderKey, (signFor) => [    signFor('coin.GAS'),    signFor('coin.TRANSFER', senderAccount, receiverAccount, amount),  ]),  setMeta({ chainId: '0', senderAccount }),  setNetworkId(NETWORK_ID),  createTransaction(),); const transaction = createTransaction(pactCommand); const output = {  cmd: '{"payload":{"exec":{"code":"(coin.transfer \\"k:dc20ab800b0420be9b1075c97e80b104b073b0405b5e2b78afd29dd74aaf5e46\\" \\"k:2f48080efe54e6eb670487f664bcaac7684b4ebfcfc8a3330ef080c9c97f7e11\\" 1.0)","data":{}}},"nonce":"kjs:nonce:1711376792115","signers":[{"pubKey":"dc20ab800b0420be9b1075c97e80b104b073b0405b5e2b78afd29dd74aaf5e46","scheme":"ED25519","clist":[{"name":"coin.GAS","args":[]},{"name":"coin.TRANSFER","args":["k:dc20ab800b0420be9b1075c97e80b104b073b0405b5e2b78afd29dd74aaf5e46","k:2f48080efe54e6eb670487f664bcaac7684b4ebfcfc8a3330ef080c9c97f7e11",{"decimal":"1"}]}]}],"meta":{"gasLimit":2500,"gasPrice":1e-8,"sender":"k:dc20ab800b0420be9b1075c97e80b104b073b0405b5e2b78afd29dd74aaf5e46","ttl":28800,"creationTime":1711376792,"chainId":"0"},"networkId":"testnet04"}',  hash: 'xYePm_YgO6-T9yIlCZWzOt2s4CkZcQwqWx9Iu5tVSLI',  sigs: [undefined],};

Runnable examples

For samples of runnable code, see the client-examples.