Skip to main content

Interact with multisig wallets using TypeScript

Introduction

If you don't know what is multisig wallet in TON, you can check it out here

Following this steps you will learn how to:

  • Create and deploy multisig wallet
  • Create, sign and send transactions with that wallet

We will create a TypeScript project and use ton library, so you need to install it first. We will also use the ton-access:

yarn add typescript @types/node ton ton-crypto ton-core buffer @orbs-network/ton-access
yarn tsc --init -t es2022

The full code of this guide is available here:

Create and deploy multisig wallet

Let's create a source file, main.ts for example. Open it in your favorite code editor and follow this guide!

At first we need to import all important stuff

import { Address, beginCell, MessageRelaxed, toNano, TonClient, WalletContractV4, MultisigWallet, MultisigOrder, MultisigOrderBuilder } from "ton";
import { KeyPair, mnemonicToPrivateKey } from 'ton-crypto';
import { getHttpEndpoint } from "@orbs-network/ton-access";

Create TonClient instance:

const endpoint = await getHttpEndpoint();
const client = new TonClient({ endpoint });

Than we need keypairs to work with:

let keyPairs: KeyPair[] = [];

let mnemonics[] = [
['orbit', 'feature', ...], //this should be the seed phrase of 24 words
['sing', 'pattern', ...],
['piece', 'deputy', ...],
['toss', 'shadow', ...],
['guard', 'nurse', ...]
];

for (let i = 0; i < mnemonics.length; i++) keyPairs[i] = await mnemonicToPrivateKey(mnemonics[i]);

There are two ways to create MultisigWallet object:

  • Import existing one from address
let addr: Address = Address.parse('EQADBXugwmn4YvWsQizHdWGgfCTN_s3qFP0Ae0pzkU-jwzoE');
let mw: MultisigWallet = await MultisigWallet.fromAddress(addr, { client });
  • Create a new one
let mw: MultisigWallet = new MultisigWallet([keyPairs[0].publicKey, keyPairs[1].publicKey], 0, 0, 1, { client });

There are also two ways to deploy it

  • Via internal message
let wallet: WalletContractV4 = WalletContractV4.create({ workchain: 0, publicKey: keyPairs[4].publicKey });
//wallet should be active and have some balance
await mw.deployInternal(wallet.sender(client.provider(wallet.address, null), keyPairs[4].secretKey), toNano('0.05'));
  • Via external message
await mw.deployExternal();

Create, sign and send an order

We need an MultisigOrderBuilder object to create a new order.

let order1: MultisigOrderBuilder = new MultisigOrderBuilder(0);

Then we can add some messages to it.

let msg: MessageRelaxed = {
body: beginCell().storeUint(0, 32).storeBuffer(Buffer.from('Hello, world!')).endCell(),
info: {
bounce: true,
bounced: false,
createdAt: 0,
createdLt: 0n,
dest: Address.parse('EQArzP5prfRJtDM5WrMNWyr9yUTAi0c9o6PfR4hkWy9UQXHx'),
forwardFee: 0n,
ihrDisabled: true,
ihrFee: 0n,
type: "internal",
value: { coins: toNano('0.01') }
}
};

order1.addMessage(msg, 3);

After you finish with adding messages, transform the MultisigOrderBuilder to MultisigOrder by calling build() method.

let order1b: MultisigOrder = order1.build();
order1b.sign(0, keyPairs[0].secretKey);

Now let's create another order, add a message to it, sign it with some other set of keys and union the signatures of these orders.

let order2: MultisigOrderBuilder = new MultisigOrderBuilder(0);
order2.addMessage(msg, 3);
let order2b = order2.build();
order2b.sign(1, keyPairs[1].secretKey);

order1b.unionSignatures(order2b); //Now order1b have also have all signatures from order2b

And finally, send the signed order:

await mw.sendOrder(order1b, keyPairs[0].secretKey);

Now build the project

yarn tsc

And run the compiled file

node main.js

If it does not throw any errors, you made everything right! Now check if your transaction succeed with any explorer or wallet.

Other methods and properties

You can easily clear messages from MultisigOrderBuilder objects:

order2.clearMessages();

You also can clear signatures from MultisigOrder objects:

order2b.clearSignatures();

And of course you can get public properties from MultisigWallet, MultisigOrderBuilder and MultisigOrder objects

  • MultisigWallet:

    • owners - Dictionary<number, Buffer> of signatures ownerId => signature
    • workchain - workchain where the wallet is deployed
    • walletId - wallet id
    • k - number of signatures required to confirm a transaction
    • address - wallet address
    • provider - ContractProvider instance
  • MultisigOrderBuilder

    • messages - array of MessageWithMode to be added to the order
    • queryId - global time until which the order is valid
  • MultisigOrder

    • payload - Cell with order payload
    • signatures - Dictionary<number, Buffer> of signatures ownerId => signature

References