Skip to main content

Upgrading from @kadena/client 0.x to 1.0.0

The highlights of the difference between 0.x and 1.0.0 are:

  • the expression generation is separate from transaction building. This allows for multiple statements per transaction
  • the client is it's own separate entity
  • signing is applied on a vanilla JS Object

Here are two examples of old to new rewrites

Sending a transaction 'transfer'

Old implementation

async function transaction(
  sender: string,
  senderPublicKey: string,
  receiver: string,
  amount: IPactDecimal,
): Promise<void> {
  const unsignedTransaction = Pact.modules.coin
    .transfer(sender, receiver, amount)
    .addCap('coin.GAS', senderPublicKey)
    .addCap('coin.TRANSFER', senderPublicKey, sender, receiver, amount)
    .setMeta({ sender }, 'testnet04');
 
  const res = await signWithChainweaver(unsignedTransaction);
 
  const sendRequests = res.map((tx) => {
    console.log('sending transaction', tx.code);
    return tx.send(testnetChain1ApiHost);
  });
 
  const sendResponses = await Promise.all(sendRequests);
  sendResponses.map(async function (sendResponse: SendResponse): Promise<void> {
    const requestKey = (await sendRequests[0]).requestKeys[0];
    await pollMain(requestKey);
    console.log(`Transaction '${requestKey}' finished`);
  });
}
 
async function pollMain(...requestKeys: string[]): Promise<void> {
  // ... some code to poll the status of the requestKeys
}
async function transaction(
  sender: string,
  senderPublicKey: string,
  receiver: string,
  amount: IPactDecimal,
): Promise<void> {
  const unsignedTransaction = Pact.modules.coin
    .transfer(sender, receiver, amount)
    .addCap('coin.GAS', senderPublicKey)
    .addCap('coin.TRANSFER', senderPublicKey, sender, receiver, amount)
    .setMeta({ sender }, 'testnet04');
 
  const res = await signWithChainweaver(unsignedTransaction);
 
  const sendRequests = res.map((tx) => {
    console.log('sending transaction', tx.code);
    return tx.send(testnetChain1ApiHost);
  });
 
  const sendResponses = await Promise.all(sendRequests);
  sendResponses.map(async function (sendResponse: SendResponse): Promise<void> {
    const requestKey = (await sendRequests[0]).requestKeys[0];
    await pollMain(requestKey);
    console.log(`Transaction '${requestKey}' finished`);
  });
}
 
async function pollMain(...requestKeys: string[]): Promise<void> {
  // ... some code to poll the status of the requestKeys
}

New implementation

const NETWORK_ID: string = 'testnet04';
 
async function transfer(
  sender: string,
  senderPublicKey: string,
  receiver: string,
  amount: IPactDecimal,
): Promise<void> {
  const transaction = Pact.builder
    .execution(
      // pact expression
      Pact.modules.coin.transfer(sender, receiver, amount),
    )
    // add signers
    .addSigner(senderPublicKey, (withCapability) => [
      // add capabilities
      withCapability('coin.GAS'),
      withCapability('coin.TRANSFER', sender, receiver, amount),
    ])
    // set chainId and sender
    .setMeta({ chainId: '0', sender })
    .setNetworkId(NETWORK_ID)
    // will create a IUnsignedTransaction { cmd, hash, sigs }
    .createTransaction();
 
  const signedTx = await signWithChainweaver(transaction);
 
  // create generic client
  const client = createClient(apiHostGenerator);
 
  // check if all necessary signatures are added
  if (isSignedTransaction(signedTx)) {
    const transactionDescriptor = await client.submit(signedTx);
    const response = await client.listen(transactionDescriptor, {});
    if (response.result.status === 'failure') {
      throw response.result.error;
    } else {
      console.log(response.result);
    }
  }
}
 
transfer(senderAccount, senderPublicKey, receiverAccount, {
  decimal: '13.37',
}).catch(console.error);
const NETWORK_ID: string = 'testnet04';
 
async function transfer(
  sender: string,
  senderPublicKey: string,
  receiver: string,
  amount: IPactDecimal,
): Promise<void> {
  const transaction = Pact.builder
    .execution(
      // pact expression
      Pact.modules.coin.transfer(sender, receiver, amount),
    )
    // add signers
    .addSigner(senderPublicKey, (withCapability) => [
      // add capabilities
      withCapability('coin.GAS'),
      withCapability('coin.TRANSFER', sender, receiver, amount),
    ])
    // set chainId and sender
    .setMeta({ chainId: '0', sender })
    .setNetworkId(NETWORK_ID)
    // will create a IUnsignedTransaction { cmd, hash, sigs }
    .createTransaction();
 
  const signedTx = await signWithChainweaver(transaction);
 
  // create generic client
  const client = createClient(apiHostGenerator);
 
  // check if all necessary signatures are added
  if (isSignedTransaction(signedTx)) {
    const transactionDescriptor = await client.submit(signedTx);
    const response = await client.listen(transactionDescriptor, {});
    if (response.result.status === 'failure') {
      throw response.result.error;
    } else {
      console.log(response.result);
    }
  }
}
 
transfer(senderAccount, senderPublicKey, receiverAccount, {
  decimal: '13.37',
}).catch(console.error);

Read from the blockchain 'getBalance'

Old implementation

async function getBalance(account: string): Promise<void> {
  // generation of transaction and expression as one, and the client is part of the transaction
  const res = await Pact.modules.coin['get-balance'](account).local(
    'http://host.com/chain/0/pact',
  );
  console.log(res);
}
 
const myAccount: string =
  'k:554754f48b16df24b552f6832dda090642ed9658559fef9f3ee1bb4637ea7c94';
 
getBalance(myAccount).catch(console.error);
async function getBalance(account: string): Promise<void> {
  // generation of transaction and expression as one, and the client is part of the transaction
  const res = await Pact.modules.coin['get-balance'](account).local(
    'http://host.com/chain/0/pact',
  );
  console.log(res);
}
 
const myAccount: string =
  'k:554754f48b16df24b552f6832dda090642ed9658559fef9f3ee1bb4637ea7c94';
 
getBalance(myAccount).catch(console.error);

New implementation:

async function getBalance(account: string): Promise<void> {
  // `Pact.builder.execution` accepts a number of `Pact.modules.<module>.<fun>` calls
  const transaction = Pact.builder
    .execution(Pact.modules.coin['get-balance'](account))
    .setMeta({ chainId: '1' })
    .createTransaction();
 
  // client creation is separate from the transaction builder
  const staticClient = createClient('http://host.com/chain/0/pact');
  const genericClient = createClient(
    ({ networkId, chainId }) =>
      `http://${networkId}.host.com/chain/${chainId}/pact`,
  );
 
  const res = await staticClient.local(transaction, {
    preflight: false,
    signatureVerification: false,
  });
 
  console.log(res);
}
 
getBalance(account).catch(console.error);
async function getBalance(account: string): Promise<void> {
  // `Pact.builder.execution` accepts a number of `Pact.modules.<module>.<fun>` calls
  const transaction = Pact.builder
    .execution(Pact.modules.coin['get-balance'](account))
    .setMeta({ chainId: '1' })
    .createTransaction();
 
  // client creation is separate from the transaction builder
  const staticClient = createClient('http://host.com/chain/0/pact');
  const genericClient = createClient(
    ({ networkId, chainId }) =>
      `http://${networkId}.host.com/chain/${chainId}/pact`,
  );
 
  const res = await staticClient.local(transaction, {
    preflight: false,
    signatureVerification: false,
  });
 
  console.log(res);
}
 
getBalance(account).catch(console.error);