New:Socket for Asana Is Now Available.Learn more
Get Started

@ton/ton

Package Overview
Dependencies
Maintainers
6
Versions
24
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ton/ton - npm Package Compare versions

Comparing version
15.3.1
to
15.4.0
+114
dist/wallets/v4/WalletContractV4.d.ts
/**
* Copyright (c) Whales Corp.
* All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import { Address, Cell, Contract, ContractProvider, MessageRelaxed, Sender, SendMode, StateInit } from "@ton/core";
import { Maybe } from "../../utils/maybe";
import { SendArgsSignable, SendArgsSigned } from "../signing/singer";
import { OutActionWalletV4, WalletV4SendArgs, WalletV4SendArgsSignable } from "./WalletContractV4Actions";
export type WalletV4BasicSendArgs = {
seqno: number;
messages: MessageRelaxed[];
sendMode?: Maybe<SendMode>;
timeout?: Maybe<number>;
};
export type Wallet4SendArgsSigned = WalletV4BasicSendArgs & SendArgsSigned;
export type Wallet4SendArgsSignable = WalletV4BasicSendArgs & SendArgsSignable;
export declare class WalletContractV4 implements Contract {
static create(args: {
workchain: number;
publicKey: Buffer;
walletId?: Maybe<number>;
}): WalletContractV4;
readonly workchain: number;
readonly publicKey: Buffer;
readonly address: Address;
readonly walletId: number;
readonly init: {
data: Cell;
code: Cell;
};
private constructor();
/**
* Get Wallet Balance
*/
getBalance(provider: ContractProvider): Promise<bigint>;
/**
* Get Wallet Seqno
*/
getSeqno(provider: ContractProvider): Promise<number>;
getIsPluginInstalled(provider: ContractProvider, pluginAddress: Address): Promise<boolean>;
getPluginsArray(provider: ContractProvider): Promise<Address[]>;
/**
* Send signed transfer
*/
send(provider: ContractProvider, message: Cell): Promise<void>;
/**
* Sign and send transfer
*/
sendTransfer(provider: ContractProvider, args: {
seqno: number;
secretKey: Buffer;
messages: MessageRelaxed[];
sendMode?: Maybe<SendMode>;
timeout?: Maybe<number>;
}): Promise<void>;
/**
* Create signed transfer
*/
createTransfer<T extends Wallet4SendArgsSigned | Wallet4SendArgsSignable>(args: T): T extends SendArgsSignable ? Promise<Cell> : Cell;
sendRequest<T extends WalletV4SendArgs & {
action: OutActionWalletV4;
}>(provider: ContractProvider, args: T): Promise<void>;
createRequest<T extends WalletV4SendArgs & {
action: OutActionWalletV4;
}>(args: T): T extends WalletV4SendArgsSignable ? Promise<Cell> : Cell;
/**
* Create sender
*/
sender(provider: ContractProvider, secretKey: Buffer): Sender;
sendAddPlugin<T extends WalletV4SendArgs & {
address: Address;
forwardAmount: bigint;
queryId?: bigint;
}>(provider: ContractProvider, args: T): Promise<void>;
sendRemovePlugin<T extends WalletV4SendArgs & {
address: Address;
forwardAmount: bigint;
queryId?: bigint;
}>(provider: ContractProvider, args: T): Promise<void>;
sendAddAndDeployPlugin<T extends WalletV4SendArgs & {
workchain: number;
stateInit: StateInit;
body: Cell;
forwardAmount: bigint;
}>(provider: ContractProvider, args: T): Promise<void>;
createAddPlugin<T extends WalletV4SendArgs & {
address: Address;
forwardAmount: bigint;
queryId?: bigint;
}>(args: T): Cell | Promise<Cell>;
createRemovePlugin<T extends WalletV4SendArgs & {
address: Address;
forwardAmount: bigint;
queryId?: bigint;
}>(args: T): Cell | Promise<Cell>;
createAddAndDeployPlugin<T extends WalletV4SendArgs & {
workchain: number;
stateInit: StateInit;
body: Cell;
forwardAmount: bigint;
}>(args: T): Cell | Promise<Cell>;
sendPluginRequestFunds(provider: ContractProvider, sender: Sender, args: {
forwardAmount: bigint;
toncoinsToWithdraw: bigint;
queryId?: bigint;
sendMode?: SendMode;
}): Promise<void>;
private createPluginRequestFundsMessage;
sendPluginRemovePlugin(provider: ContractProvider, sender: Sender, amount: bigint, queryId?: bigint): Promise<void>;
private createPluginRemovePluginMessage;
}
"use strict";
/**
* Copyright (c) Whales Corp.
* All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.WalletContractV4 = void 0;
const core_1 = require("@ton/core");
const createWalletTransfer_1 = require("../signing/createWalletTransfer");
class WalletContractV4 {
static create(args) {
return new WalletContractV4(args.workchain, args.publicKey, args.walletId);
}
constructor(workchain, publicKey, walletId) {
// Resolve parameters
this.workchain = workchain;
this.publicKey = publicKey;
if (walletId !== null && walletId !== undefined) {
this.walletId = walletId;
}
else {
this.walletId = 698983191 + workchain;
}
// Build initial code and data
let code = core_1.Cell.fromBoc(Buffer.from('te6ccgECFAEAAtQAART/APSkE/S88sgLAQIBIAIDAgFIBAUE+PKDCNcYINMf0x/THwL4I7vyZO1E0NMf0x/T//QE0VFDuvKhUVG68qIF+QFUEGT5EPKj+AAkpMjLH1JAyx9SMMv/UhD0AMntVPgPAdMHIcAAn2xRkyDXSpbTB9QC+wDoMOAhwAHjACHAAuMAAcADkTDjDQOkyMsfEssfy/8QERITAubQAdDTAyFxsJJfBOAi10nBIJJfBOAC0x8hghBwbHVnvSKCEGRzdHK9sJJfBeAD+kAwIPpEAcjKB8v/ydDtRNCBAUDXIfQEMFyBAQj0Cm+hMbOSXwfgBdM/yCWCEHBsdWe6kjgw4w0DghBkc3RyupJfBuMNBgcCASAICQB4AfoA9AQw+CdvIjBQCqEhvvLgUIIQcGx1Z4MesXCAGFAEywUmzxZY+gIZ9ADLaRfLH1Jgyz8gyYBA+wAGAIpQBIEBCPRZMO1E0IEBQNcgyAHPFvQAye1UAXKwjiOCEGRzdHKDHrFwgBhQBcsFUAPPFiP6AhPLassfyz/JgED7AJJfA+ICASAKCwBZvSQrb2omhAgKBrkPoCGEcNQICEekk30pkQzmkD6f+YN4EoAbeBAUiYcVnzGEAgFYDA0AEbjJftRNDXCx+AA9sp37UTQgQFA1yH0BDACyMoHy//J0AGBAQj0Cm+hMYAIBIA4PABmtznaiaEAga5Drhf/AABmvHfaiaEAQa5DrhY/AAG7SB/oA1NQi+QAFyMoHFcv/ydB3dIAYyMsFywIizxZQBfoCFMtrEszMyXP7AMhAFIEBCPRR8qcCAHCBAQjXGPoA0z/IVCBHgQEI9FHyp4IQbm90ZXB0gBjIywXLAlAGzxZQBPoCFMtqEssfyz/Jc/sAAgBsgQEI1xj6ANM/MFIkgQEI9Fnyp4IQZHN0cnB0gBjIywXLAlAFzxZQA/oCE8tqyx8Syz/Jc/sAAAr0AMntVA==', 'base64'))[0];
let data = (0, core_1.beginCell)()
.storeUint(0, 32) // Seqno
.storeUint(this.walletId, 32)
.storeBuffer(this.publicKey)
.storeBit(0) // Empty plugins dict
.endCell();
this.init = { code, data };
this.address = (0, core_1.contractAddress)(workchain, { code, data });
}
/**
* Get Wallet Balance
*/
async getBalance(provider) {
let state = await provider.getState();
return state.balance;
}
/**
* Get Wallet Seqno
*/
async getSeqno(provider) {
let state = await provider.getState();
if (state.state.type === 'active') {
let res = await provider.get('seqno', []);
return res.stack.readNumber();
}
else {
return 0;
}
}
async getIsPluginInstalled(provider, pluginAddress) {
const state = await provider.getState();
if (state.state.type !== 'active') {
return false;
}
const wc = BigInt(pluginAddress.workChain);
const addrHash = BigInt('0x' + pluginAddress.hash.toString('hex'));
const res = await provider.get('is_plugin_installed', [
{ type: 'int', value: wc },
{ type: 'int', value: addrHash }
]);
return res.stack.readBoolean();
}
async getPluginsArray(provider) {
const state = await provider.getState();
if (state.state.type !== 'active') {
return [];
}
const res = await provider.get('get_plugin_list', []);
return res.stack.readLispList().map(item => {
if (item.type !== 'tuple') {
throw Error('Not a tuple');
}
const entry = new core_1.TupleReader(item.items);
const workchain = entry.readNumber();
const addrHash = entry.readBigNumber();
const addressHex = addrHash.toString(16).padStart(64, '0');
return core_1.Address.parseRaw(`${workchain}:${addressHex}`);
});
}
/**
* Send signed transfer
*/
async send(provider, message) {
await provider.external(message);
}
/**
* Sign and send transfer
*/
async sendTransfer(provider, args) {
let transfer = this.createTransfer(args);
await this.send(provider, transfer);
}
/**
* Create signed transfer
*/
createTransfer(args) {
return this.createRequest({
seqno: args.seqno,
timeout: args.timeout,
action: {
type: 'sendMsg',
messages: args.messages,
sendMode: args.sendMode,
},
...('secretKey' in args
? { secretKey: args.secretKey }
: { signer: args.signer })
});
}
async sendRequest(provider, args) {
const action = await this.createRequest(args);
await this.send(provider, action);
}
createRequest(args) {
return (0, createWalletTransfer_1.createWalletTransferV4)({
...args,
walletId: this.walletId
});
}
/**
* Create sender
*/
sender(provider, secretKey) {
return {
send: async (args) => {
let seqno = await this.getSeqno(provider);
let transfer = this.createTransfer({
seqno,
secretKey,
sendMode: args.sendMode,
messages: [(0, core_1.internal)({
to: args.to,
value: args.value,
extracurrency: args.extracurrency,
init: args.init,
body: args.body,
bounce: args.bounce
})]
});
await this.send(provider, transfer);
}
};
}
async sendAddPlugin(provider, args) {
const request = await this.createAddPlugin(args);
return await this.send(provider, request);
}
async sendRemovePlugin(provider, args) {
const request = await this.createRemovePlugin(args);
return await this.send(provider, request);
}
async sendAddAndDeployPlugin(provider, args) {
const request = await this.createAddAndDeployPlugin(args);
return await this.send(provider, request);
}
createAddPlugin(args) {
return this.createRequest({
action: {
type: 'addPlugin',
address: args.address,
forwardAmount: args.forwardAmount,
queryId: args.queryId,
},
...args
});
}
createRemovePlugin(args) {
return this.createRequest({
action: {
type: 'removePlugin',
address: args.address,
forwardAmount: args.forwardAmount,
queryId: args.queryId,
},
...args
});
}
createAddAndDeployPlugin(args) {
return this.createRequest({
action: {
type: 'addAndDeployPlugin',
workchain: args.workchain,
stateInit: args.stateInit,
body: args.body,
forwardAmount: args.forwardAmount
},
...args
});
}
async sendPluginRequestFunds(provider, sender, args) {
await provider.internal(sender, {
value: args.forwardAmount,
body: this.createPluginRequestFundsMessage(args),
sendMode: args.sendMode
});
}
createPluginRequestFundsMessage(args) {
return (0, core_1.beginCell)()
.storeUint(0x706c7567, 32)
.storeUint(args.queryId ?? 0, 64)
.storeCoins(args.toncoinsToWithdraw)
.storeDict(null)
.endCell();
}
async sendPluginRemovePlugin(provider, sender, amount, queryId) {
await provider.internal(sender, {
value: amount,
body: this.createPluginRemovePluginMessage(queryId),
});
}
createPluginRemovePluginMessage(queryId) {
return (0, core_1.beginCell)()
.storeUint(0x64737472, 32)
.storeUint(queryId ?? 0, 64)
.endCell();
}
}
exports.WalletContractV4 = WalletContractV4;
/**
* Copyright (c) Whales Corp.
* All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
export {};
"use strict";
/**
* Copyright (c) Whales Corp.
* All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
Object.defineProperty(exports, "__esModule", { value: true });
const randomTestKey_1 = require("../../utils/randomTestKey");
const testWallets_1 = require("../../utils/testWallets");
const WalletContractV4_1 = require("./WalletContractV4");
const createTestClient4_1 = require("../../utils/createTestClient4");
const core_1 = require("@ton/core");
describe('WalletContractV4', () => {
it('should has balance and correct address', async () => {
// Create contract
let client = (0, createTestClient4_1.createTestClient4)();
let key = (0, randomTestKey_1.randomTestKey)('v4-treasure');
let contract = client.open(WalletContractV4_1.WalletContractV4.create({ workchain: 0, publicKey: key.publicKey }));
let balance = await contract.getBalance();
// Check parameters
expect(contract.address.equals(core_1.Address.parse('EQDnBF4JTFKHTYjulEJyNd4dstLGH1m51UrLdu01_tw4z2Au'))).toBe(true);
expect(balance > 0n).toBe(true);
});
it('should perform transfer', async () => {
// Create contract
let client = (0, createTestClient4_1.createTestClient4)();
let key = (0, randomTestKey_1.randomTestKey)('v4-treasure');
let contract = client.open(WalletContractV4_1.WalletContractV4.create({ workchain: 0, publicKey: key.publicKey }));
// Prepare transfer
let seqno = await contract.getSeqno();
let transfer = contract.createTransfer({
seqno,
secretKey: key.secretKey,
messages: [(0, core_1.internal)({
to: 'kQD6oPnzaaAMRW24R8F0_nlSsJQni0cGHntR027eT9_sgtwt',
value: '0.1',
body: 'Hello world: 1'
}), (0, core_1.internal)({
to: 'kQD6oPnzaaAMRW24R8F0_nlSsJQni0cGHntR027eT9_sgtwt',
value: '0.1',
body: 'Hello world: 2'
})]
});
// Perform transfer
await contract.send(transfer);
// Awaiting update
await (0, testWallets_1.tillNextSeqno)(contract, seqno);
});
it('should perform extra currency transfer', async () => {
// Create contract
let client = (0, createTestClient4_1.createTestClient4)();
let key = (0, randomTestKey_1.randomTestKey)('v4-treasure');
let contract = client.open(WalletContractV4_1.WalletContractV4.create({ workchain: 0, publicKey: key.publicKey }));
// Prepare transfer
let seqno = await contract.getSeqno();
let transfer = contract.createTransfer({
seqno,
secretKey: key.secretKey,
messages: [(0, core_1.internal)({
to: 'kQD6oPnzaaAMRW24R8F0_nlSsJQni0cGHntR027eT9_sgtwt',
value: '0.01',
extracurrency: { 100: BigInt(10 ** 6) },
body: 'Hello extra currency v4'
})]
});
// Perform transfer
await contract.send(transfer);
// Awaiting update
await (0, testWallets_1.tillNextSeqno)(contract, seqno);
});
describe('plugins', () => {
let client;
let walletKey;
let contract;
let randomAddress;
let pluginKey;
let pluginContract;
beforeEach(() => {
client = (0, createTestClient4_1.createTestClient4)();
walletKey = (0, randomTestKey_1.randomTestKey)('v4-treasure');
contract = client.open(WalletContractV4_1.WalletContractV4.create({ workchain: 0, publicKey: walletKey.publicKey }));
pluginContract = client.open(WalletContractV4_1.WalletContractV4.create({ workchain: 0, publicKey: walletKey.publicKey }));
randomAddress = WalletContractV4_1.WalletContractV4.create({
workchain: 0,
publicKey: (0, randomTestKey_1.randomTestKey)('v4-test-plugin').publicKey
}).address;
});
it('should install plugin', async () => {
let seqno = await contract.getSeqno();
await contract.sendRequest({
seqno: await contract.getSeqno(),
secretKey: walletKey.secretKey,
action: {
type: 'addPlugin',
address: randomAddress,
forwardAmount: (0, core_1.toNano)('0.01'),
}
});
await (0, testWallets_1.tillNextSeqno)(contract, seqno);
});
it('should return plugin in get methods', async () => {
expect(await contract.getIsPluginInstalled(randomAddress)).toBeTruthy();
const plugins = await contract.getPluginsArray();
expect(plugins.find(plugin => plugin.equals(randomAddress))).toBeTruthy();
});
it('should uninstall plugin', async () => {
let seqno = await contract.getSeqno();
await contract.sendRequest({
seqno: await contract.getSeqno(),
secretKey: walletKey.secretKey,
action: {
type: 'removePlugin',
address: randomAddress,
forwardAmount: (0, core_1.toNano)('0.01'),
}
});
await (0, testWallets_1.tillNextSeqno)(contract, seqno);
});
it('should return plugin in get methods', async () => {
expect(await contract.getIsPluginInstalled(randomAddress)).toBeFalsy();
const plugins = await contract.getPluginsArray();
plugins.forEach(plugin => {
expect(plugin.equals(randomAddress)).toBeFalsy();
});
});
it('should install and deploy plugin', async () => {
let seqno = await contract.getSeqno();
await contract.sendRequest({
seqno: await contract.getSeqno(),
secretKey: walletKey.secretKey,
action: {
type: 'addAndDeployPlugin',
workchain: 0,
stateInit: pluginContract.init,
body: (0, core_1.beginCell)().endCell(),
forwardAmount: (0, core_1.toNano)('0.1'),
}
});
await (0, testWallets_1.tillNextSeqno)(contract, seqno);
});
it('should withdraw funds by plugin request', async () => {
let seqno = await contract.getSeqno();
await pluginContract.sendPluginRequestFunds(pluginContract.sender(walletKey.secretKey), {
forwardAmount: (0, core_1.toNano)('0.01'),
toncoinsToWithdraw: (0, core_1.toNano)('0.05')
});
await (0, testWallets_1.tillNextSeqno)(contract, seqno);
});
it('should delete plugin by plugin request', async () => {
let seqno = await pluginContract.getSeqno();
await pluginContract.sendPluginRemovePlugin(pluginContract.sender(walletKey.secretKey), (0, core_1.toNano)('0.01'));
await (0, testWallets_1.tillNextSeqno)(contract, seqno);
});
});
});
import { Maybe } from "../../utils/maybe";
import { Address, Builder, Cell, MessageRelaxed, SendMode, StateInit, Slice } from "@ton/core";
import { SendArgsSignable, SendArgsSigned } from "../signing/singer";
export type WalletV4ExtendedSendArgs = {
seqno: number;
timeout?: Maybe<number>;
};
export interface OutActionSendMsg {
type: 'sendMsg';
messages: MessageRelaxed[];
sendMode?: Maybe<SendMode>;
}
export interface OutActionAddAndDeployPlugin {
type: 'addAndDeployPlugin';
workchain: number;
stateInit: StateInit;
body: Cell;
forwardAmount: bigint;
}
export interface OutActionAddPlugin {
type: 'addPlugin';
address: Address;
forwardAmount: bigint;
queryId?: bigint;
}
export interface OutActionRemovePlugin {
type: 'removePlugin';
address: Address;
forwardAmount: bigint;
queryId?: bigint;
}
export type OutActionWalletV4 = OutActionSendMsg | OutActionAddAndDeployPlugin | OutActionAddPlugin | OutActionRemovePlugin;
export type WalletV4SendArgsSigned = WalletV4ExtendedSendArgs & SendArgsSigned;
export type WalletV4SendArgsSignable = WalletV4ExtendedSendArgs & SendArgsSignable;
export type WalletV4SendArgs = WalletV4SendArgsSigned | WalletV4SendArgsSignable;
export declare function storeExtendedAction(action: OutActionWalletV4): (builder: Builder) => void;
export declare function loadExtendedAction(slice: Slice): OutActionWalletV4;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.storeExtendedAction = storeExtendedAction;
exports.loadExtendedAction = loadExtendedAction;
const core_1 = require("@ton/core");
function storeExtendedAction(action) {
return (builder) => {
switch (action.type) {
case 'sendMsg':
builder.storeUint(0, 8);
for (let m of action.messages) {
builder.storeUint(action.sendMode ?? core_1.SendMode.NONE, 8);
builder.storeRef((0, core_1.beginCell)().store((0, core_1.storeMessageRelaxed)(m)));
}
break;
case 'addAndDeployPlugin':
builder.storeUint(1, 8);
builder.storeInt(action.workchain, 8);
builder.storeCoins(action.forwardAmount);
builder.storeRef((0, core_1.beginCell)().store((0, core_1.storeStateInit)(action.stateInit)));
builder.storeRef(action.body);
break;
case 'addPlugin':
builder.storeUint(2, 8);
builder.storeInt(action.address.workChain, 8);
builder.storeBuffer(action.address.hash);
builder.storeCoins(action.forwardAmount);
builder.storeUint(action.queryId ?? 0n, 64);
break;
case 'removePlugin':
builder.storeUint(3, 8);
builder.storeInt(action.address.workChain, 8);
builder.storeBuffer(action.address.hash);
builder.storeCoins(action.forwardAmount);
builder.storeUint(action.queryId ?? 0n, 64);
break;
default:
throw new Error(`Unsupported plugin action`);
}
};
}
function loadExtendedAction(slice) {
const actionType = slice.loadUint(8);
switch (actionType) {
case 0: {
const messages = [];
let sendModeValue = undefined;
while (slice.remainingRefs > 0) {
if (slice.remainingBits < 8) {
throw new Error('Invalid sendMsg action: insufficient bits for send mode');
}
const mode = slice.loadUint(8);
const messageCell = slice.loadRef();
const message = (0, core_1.loadMessageRelaxed)(messageCell.beginParse());
if (sendModeValue === undefined) {
sendModeValue = mode;
}
else if (sendModeValue !== mode) {
throw new Error('Invalid sendMsg action: mixed send modes are not supported');
}
messages.push(message);
}
return {
type: 'sendMsg',
messages,
sendMode: sendModeValue,
};
}
case 1: {
const workchain = slice.loadInt(8);
const forwardAmount = slice.loadCoins();
const stateInit = (0, core_1.loadStateInit)(slice.loadRef().beginParse());
const body = slice.loadRef();
return {
type: 'addAndDeployPlugin',
workchain,
stateInit,
body,
forwardAmount,
};
}
case 2: {
const workchain = slice.loadInt(8);
const hash = slice.loadBuffer(32);
const forwardAmount = slice.loadCoins();
const queryId = slice.loadUintBig(64);
return {
type: 'addPlugin',
address: new core_1.Address(workchain, hash),
forwardAmount,
queryId: queryId === 0n ? undefined : queryId,
};
}
case 3: {
const workchain = slice.loadInt(8);
const hash = slice.loadBuffer(32);
const forwardAmount = slice.loadCoins();
const queryId = slice.loadUintBig(64);
return {
type: 'removePlugin',
address: new core_1.Address(workchain, hash),
forwardAmount,
queryId: queryId === 0n ? undefined : queryId,
};
}
default:
throw new Error(`Unsupported action with opcode ${actionType}`);
}
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const core_1 = require("@ton/core");
const WalletContractV4Actions_1 = require("./WalletContractV4Actions");
describe('Wallet V5R1 actions', () => {
it('should serialize and deserialize OutActionSendMsg', async () => {
const msg = {
type: 'sendMsg',
messages: [(0, core_1.internal)({
to: new core_1.Address(0, Buffer.alloc(32, 0xaa)),
value: '0.001',
})],
sendMode: core_1.SendMode.PAY_GAS_SEPARATELY,
};
const serialized = (0, core_1.beginCell)().store((0, WalletContractV4Actions_1.storeExtendedAction)(msg)).endCell();
const deserialized = (0, WalletContractV4Actions_1.loadExtendedAction)(serialized.beginParse());
if (deserialized.type !== 'sendMsg')
throw new Error();
expect(deserialized.messages.length).toEqual(msg.messages.length);
expect(deserialized.messages[0].info.dest.toString()).toEqual(msg.messages[0].info.dest.toString());
expect(deserialized.sendMode).toEqual(msg.sendMode);
});
it('should serialize and deserialize OutActionAddAndDeployPlugin', () => {
const stateInit = {
code: (0, core_1.beginCell)().storeUint(0xa, 4).endCell(),
data: (0, core_1.beginCell)().storeUint(0xb, 4).endCell(),
};
const action = {
type: 'addAndDeployPlugin',
workchain: -1,
stateInit,
body: (0, core_1.beginCell)().storeUint(0xcc, 8).endCell(),
forwardAmount: 1000n,
};
const serialized = (0, core_1.beginCell)().store((0, WalletContractV4Actions_1.storeExtendedAction)(action)).endCell();
const deserialized = (0, WalletContractV4Actions_1.loadExtendedAction)(serialized.beginParse());
if (deserialized.type !== 'addAndDeployPlugin')
throw new Error();
expect(deserialized.workchain).toEqual(action.workchain);
expect(deserialized.forwardAmount).toEqual(action.forwardAmount);
expect(deserialized.body.equals(action.body)).toBe(true);
expect(deserialized.stateInit.code?.equals(action.stateInit.code)).toBe(true);
expect(deserialized.stateInit.data?.equals(action.stateInit.data)).toBe(true);
});
it('should serialize and deserialize OutActionAddPlugin', () => {
const action = {
type: 'addPlugin',
address: new core_1.Address(0, Buffer.alloc(32, 0xaa)),
forwardAmount: 123n,
queryId: 77n,
};
const serialized = (0, core_1.beginCell)().store((0, WalletContractV4Actions_1.storeExtendedAction)(action)).endCell();
const deserialized = (0, WalletContractV4Actions_1.loadExtendedAction)(serialized.beginParse());
if (deserialized.type !== 'addPlugin')
throw new Error();
expect(deserialized.address.equals(action.address)).toBe(true);
expect(deserialized.forwardAmount).toEqual(action.forwardAmount);
expect(deserialized.queryId).toEqual(action.queryId);
});
it('should serialize and deserialize OutActionRemovePlugin', () => {
const action = {
type: 'removePlugin',
address: new core_1.Address(0, Buffer.alloc(32, 0xbb)),
forwardAmount: 987654321n,
};
const serialized = (0, core_1.beginCell)().store((0, WalletContractV4Actions_1.storeExtendedAction)(action)).endCell();
const deserialized = (0, WalletContractV4Actions_1.loadExtendedAction)(serialized.beginParse());
if (deserialized.type !== 'removePlugin')
throw new Error();
expect(deserialized.address.equals(action.address)).toBe(true);
expect(deserialized.forwardAmount).toEqual(action.forwardAmount);
expect(deserialized.queryId).toBeUndefined();
});
});
+5
-4

@@ -11,6 +11,6 @@ /**

import { WalletV5BetaPackedCell, WalletV5BetaSendArgs, WalletV5BetaSendArgsExtensionAuth } from "../v5beta/WalletContractV5Beta";
import { Wallet4SendArgsSignable, Wallet4SendArgsSigned } from "../WalletContractV4";
import { WalletV3SendArgsSignable, WalletV3SendArgsSigned } from "../WalletContractV3Types";
import { OutActionExtended } from "../v5beta/WalletV5OutActions";
import { Wallet5VR1SendArgsExtensionAuth, WalletV5R1PackedCell, WalletV5R1SendArgs } from "../v5r1/WalletContractV5R1";
import { OutActionWalletV4, WalletV4SendArgs, WalletV4SendArgsSignable } from "../v4/WalletContractV4Actions";
export declare function createWalletTransferV1(args: {

@@ -33,6 +33,7 @@ seqno: number;

}): T extends WalletV3SendArgsSignable ? Promise<Cell> : Cell;
export declare function createWalletTransferV4<T extends Wallet4SendArgsSignable | Wallet4SendArgsSigned>(args: T & {
sendMode: number;
export declare function createWalletTransferV4<T extends WalletV4SendArgs & {
action: OutActionWalletV4;
}>(args: T & {
walletId: number;
}): T extends Wallet4SendArgsSignable ? Promise<Cell> : Cell;
}): T extends WalletV4SendArgsSignable ? Promise<Cell> : Cell;
export declare function createWalletTransferV5Beta<T extends WalletV5BetaSendArgs>(args: T extends WalletV5BetaSendArgsExtensionAuth ? T & {

@@ -39,0 +40,0 @@ actions: (OutActionSendMsg | OutActionExtended)[];

@@ -23,2 +23,3 @@ "use strict";

const WalletV5R1Actions_1 = require("../v5r1/WalletV5R1Actions");
const WalletContractV4Actions_1 = require("../v4/WalletContractV4Actions");
function packSignatureToFront(signature, signingMessage) {

@@ -108,6 +109,2 @@ const body = (0, core_1.beginCell)()

function createWalletTransferV4(args) {
// Check number of messages
if (args.messages.length > 4) {
throw Error("Maximum number of messages in a single transfer is 4");
}
let signingMessage = (0, core_1.beginCell)()

@@ -124,7 +121,3 @@ .storeUint(args.walletId, 32);

signingMessage.storeUint(args.seqno, 32);
signingMessage.storeUint(0, 8); // Simple order
for (let m of args.messages) {
signingMessage.storeUint(args.sendMode, 8);
signingMessage.storeRef((0, core_1.beginCell)().store((0, core_1.storeMessageRelaxed)(m)));
}
signingMessage.store((0, WalletContractV4Actions_1.storeExtendedAction)(args.action));
return (0, singer_1.signPayload)(args, signingMessage, packSignatureToFront);

@@ -131,0 +124,0 @@ }

@@ -19,3 +19,3 @@ "use strict";

const val = new core_1.BitReader(new core_1.BitString(typeof value === 'bigint' ?
Buffer.from(value.toString(16), 'hex') :
Buffer.from(value.toString(16).padStart(8, '0'), 'hex') :
value instanceof core_1.Slice ? value.loadBuffer(4) : value, 0, 32)).loadInt(32);

@@ -22,0 +22,0 @@ const context = BigInt(val) ^ BigInt(networkGlobalId);

@@ -43,2 +43,33 @@ "use strict";

});
it('Should deserialize correctly in all modes', async () => {
const getRandom = (min, max) => {
return Math.round(Math.random() * (max - min) + min);
};
const subwalletMax = (2 ** 15) - 1;
const randomSubwallet = () => getRandom(1, subwalletMax - 2);
const randomBunch = Array(10).fill(0).map(randomSubwallet);
for (let networkId of [-239, -3]) {
for (let testWc of [0, -1]) {
for (let testSubwallet of [0, subwalletMax, ...randomBunch]) {
const expected = {
networkGlobalId: networkId,
context: {
walletVersion: 'v5r1',
workchain: testWc,
subwalletNumber: testSubwallet
}
};
const packed = (0, core_1.beginCell)().store((0, WalletV5R1WalletId_1.storeWalletIdV5R1)(expected)).endCell();
let unpacked = (0, WalletV5R1WalletId_1.loadWalletIdV5R1)(packed.beginParse(), networkId);
expect(unpacked).toEqual(expected);
const intVal = BigInt(packed.beginParse().loadInt(32));
unpacked = (0, WalletV5R1WalletId_1.loadWalletIdV5R1)(intVal, networkId);
expect(unpacked).toEqual(expected);
const buffVal = packed.beginParse().loadBuffer(4);
unpacked = (0, WalletV5R1WalletId_1.loadWalletIdV5R1)(buffVal, networkId);
expect(unpacked).toEqual(expected);
}
}
}
});
it('Should serialise wallet id', () => {

@@ -45,0 +76,0 @@ const walletId = {

@@ -1,64 +0,2 @@

/**
* Copyright (c) Whales Corp.
* All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import { Address, Cell, Contract, ContractProvider, MessageRelaxed, Sender, SendMode } from "@ton/core";
import { Maybe } from "../utils/maybe";
import { SendArgsSignable, SendArgsSigned } from "./signing/singer";
export type WalletV4BasicSendArgs = {
seqno: number;
messages: MessageRelaxed[];
sendMode?: Maybe<SendMode>;
timeout?: Maybe<number>;
};
export type Wallet4SendArgsSigned = WalletV4BasicSendArgs & SendArgsSigned;
export type Wallet4SendArgsSignable = WalletV4BasicSendArgs & SendArgsSignable;
export declare class WalletContractV4 implements Contract {
static create(args: {
workchain: number;
publicKey: Buffer;
walletId?: Maybe<number>;
}): WalletContractV4;
readonly workchain: number;
readonly publicKey: Buffer;
readonly address: Address;
readonly walletId: number;
readonly init: {
data: Cell;
code: Cell;
};
private constructor();
/**
* Get Wallet Balance
*/
getBalance(provider: ContractProvider): Promise<bigint>;
/**
* Get Wallet Seqno
*/
getSeqno(provider: ContractProvider): Promise<number>;
/**
* Send signed transfer
*/
send(provider: ContractProvider, message: Cell): Promise<void>;
/**
* Sign and send transfer
*/
sendTransfer(provider: ContractProvider, args: {
seqno: number;
secretKey: Buffer;
messages: MessageRelaxed[];
sendMode?: Maybe<SendMode>;
timeout?: Maybe<number>;
}): Promise<void>;
/**
* Create signed transfer
*/
createTransfer<T extends Wallet4SendArgsSigned | Wallet4SendArgsSignable>(args: T): T extends Wallet4SendArgsSignable ? Promise<Cell> : Cell;
/**
* Create sender
*/
sender(provider: ContractProvider, secretKey: Buffer): Sender;
}
export * from './v4/WalletContractV4';
export * from './v4/WalletContractV4Actions';
"use strict";
/**
* Copyright (c) Whales Corp.
* All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.WalletContractV4 = void 0;
const core_1 = require("@ton/core");
const createWalletTransfer_1 = require("./signing/createWalletTransfer");
class WalletContractV4 {
static create(args) {
return new WalletContractV4(args.workchain, args.publicKey, args.walletId);
}
constructor(workchain, publicKey, walletId) {
// Resolve parameters
this.workchain = workchain;
this.publicKey = publicKey;
if (walletId !== null && walletId !== undefined) {
this.walletId = walletId;
}
else {
this.walletId = 698983191 + workchain;
}
// Build initial code and data
let code = core_1.Cell.fromBoc(Buffer.from('te6ccgECFAEAAtQAART/APSkE/S88sgLAQIBIAIDAgFIBAUE+PKDCNcYINMf0x/THwL4I7vyZO1E0NMf0x/T//QE0VFDuvKhUVG68qIF+QFUEGT5EPKj+AAkpMjLH1JAyx9SMMv/UhD0AMntVPgPAdMHIcAAn2xRkyDXSpbTB9QC+wDoMOAhwAHjACHAAuMAAcADkTDjDQOkyMsfEssfy/8QERITAubQAdDTAyFxsJJfBOAi10nBIJJfBOAC0x8hghBwbHVnvSKCEGRzdHK9sJJfBeAD+kAwIPpEAcjKB8v/ydDtRNCBAUDXIfQEMFyBAQj0Cm+hMbOSXwfgBdM/yCWCEHBsdWe6kjgw4w0DghBkc3RyupJfBuMNBgcCASAICQB4AfoA9AQw+CdvIjBQCqEhvvLgUIIQcGx1Z4MesXCAGFAEywUmzxZY+gIZ9ADLaRfLH1Jgyz8gyYBA+wAGAIpQBIEBCPRZMO1E0IEBQNcgyAHPFvQAye1UAXKwjiOCEGRzdHKDHrFwgBhQBcsFUAPPFiP6AhPLassfyz/JgED7AJJfA+ICASAKCwBZvSQrb2omhAgKBrkPoCGEcNQICEekk30pkQzmkD6f+YN4EoAbeBAUiYcVnzGEAgFYDA0AEbjJftRNDXCx+AA9sp37UTQgQFA1yH0BDACyMoHy//J0AGBAQj0Cm+hMYAIBIA4PABmtznaiaEAga5Drhf/AABmvHfaiaEAQa5DrhY/AAG7SB/oA1NQi+QAFyMoHFcv/ydB3dIAYyMsFywIizxZQBfoCFMtrEszMyXP7AMhAFIEBCPRR8qcCAHCBAQjXGPoA0z/IVCBHgQEI9FHyp4IQbm90ZXB0gBjIywXLAlAGzxZQBPoCFMtqEssfyz/Jc/sAAgBsgQEI1xj6ANM/MFIkgQEI9Fnyp4IQZHN0cnB0gBjIywXLAlAFzxZQA/oCE8tqyx8Syz/Jc/sAAAr0AMntVA==', 'base64'))[0];
let data = (0, core_1.beginCell)()
.storeUint(0, 32) // Seqno
.storeUint(this.walletId, 32)
.storeBuffer(this.publicKey)
.storeBit(0) // Empty plugins dict
.endCell();
this.init = { code, data };
this.address = (0, core_1.contractAddress)(workchain, { code, data });
}
/**
* Get Wallet Balance
*/
async getBalance(provider) {
let state = await provider.getState();
return state.balance;
}
/**
* Get Wallet Seqno
*/
async getSeqno(provider) {
let state = await provider.getState();
if (state.state.type === 'active') {
let res = await provider.get('seqno', []);
return res.stack.readNumber();
}
else {
return 0;
}
}
/**
* Send signed transfer
*/
async send(provider, message) {
await provider.external(message);
}
/**
* Sign and send transfer
*/
async sendTransfer(provider, args) {
let transfer = this.createTransfer(args);
await this.send(provider, transfer);
}
/**
* Create signed transfer
*/
createTransfer(args) {
return (0, createWalletTransfer_1.createWalletTransferV4)({
...args,
sendMode: args.sendMode ?? core_1.SendMode.PAY_GAS_SEPARATELY,
walletId: this.walletId
});
}
/**
* Create sender
*/
sender(provider, secretKey) {
return {
send: async (args) => {
let seqno = await this.getSeqno(provider);
let transfer = this.createTransfer({
seqno,
secretKey,
sendMode: args.sendMode,
messages: [(0, core_1.internal)({
to: args.to,
value: args.value,
extracurrency: args.extracurrency,
init: args.init,
body: args.body,
bounce: args.bounce
})]
});
await this.send(provider, transfer);
}
};
}
}
exports.WalletContractV4 = WalletContractV4;
__exportStar(require("./v4/WalletContractV4"), exports);
__exportStar(require("./v4/WalletContractV4Actions"), exports);
{
"name": "@ton/ton",
"version": "15.3.1",
"version": "15.4.0",
"repository": "https://github.com/ton-org/ton.git",

@@ -19,3 +19,3 @@ "author": "Whales Corp. <developers@whalescorp.com>",

"@release-it/keep-a-changelog": "^5.0.0",
"@ton/core": "^0.60.0",
"@ton/core": "^0.62.0",
"@ton/crypto": "3.2.0",

@@ -51,3 +51,3 @@ "@ton/emulator": "^2.1.1",

"peerDependencies": {
"@ton/core": ">=0.60.0",
"@ton/core": ">=0.62.0 <1.0.0",
"@ton/crypto": ">=3.2.0"

@@ -54,0 +54,0 @@ },

/**
* Copyright (c) Whales Corp.
* All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
export {};
"use strict";
/**
* Copyright (c) Whales Corp.
* All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
Object.defineProperty(exports, "__esModule", { value: true });
const randomTestKey_1 = require("../utils/randomTestKey");
const testWallets_1 = require("../utils/testWallets");
const WalletContractV4_1 = require("./WalletContractV4");
const createTestClient4_1 = require("../utils/createTestClient4");
const core_1 = require("@ton/core");
describe('WalletContractV4', () => {
it('should has balance and correct address', async () => {
// Create contract
let client = (0, createTestClient4_1.createTestClient4)();
let key = (0, randomTestKey_1.randomTestKey)('v4-treasure');
let contract = client.open(WalletContractV4_1.WalletContractV4.create({ workchain: 0, publicKey: key.publicKey }));
let balance = await contract.getBalance();
// Check parameters
expect(contract.address.equals(core_1.Address.parse('EQDnBF4JTFKHTYjulEJyNd4dstLGH1m51UrLdu01_tw4z2Au'))).toBe(true);
expect(balance > 0n).toBe(true);
});
it('should perform transfer', async () => {
// Create contract
let client = (0, createTestClient4_1.createTestClient4)();
let key = (0, randomTestKey_1.randomTestKey)('v4-treasure');
let contract = client.open(WalletContractV4_1.WalletContractV4.create({ workchain: 0, publicKey: key.publicKey }));
// Prepare transfer
let seqno = await contract.getSeqno();
let transfer = contract.createTransfer({
seqno,
secretKey: key.secretKey,
messages: [(0, core_1.internal)({
to: 'kQD6oPnzaaAMRW24R8F0_nlSsJQni0cGHntR027eT9_sgtwt',
value: '0.1',
body: 'Hello world: 1'
}), (0, core_1.internal)({
to: 'kQD6oPnzaaAMRW24R8F0_nlSsJQni0cGHntR027eT9_sgtwt',
value: '0.1',
body: 'Hello world: 2'
})]
});
// Perform transfer
await contract.send(transfer);
// Awaiting update
await (0, testWallets_1.tillNextSeqno)(contract, seqno);
});
it('should perform extra currency transfer', async () => {
// Create contract
let client = (0, createTestClient4_1.createTestClient4)();
let key = (0, randomTestKey_1.randomTestKey)('v4-treasure');
let contract = client.open(WalletContractV4_1.WalletContractV4.create({ workchain: 0, publicKey: key.publicKey }));
// Prepare transfer
let seqno = await contract.getSeqno();
let transfer = contract.createTransfer({
seqno,
secretKey: key.secretKey,
messages: [(0, core_1.internal)({
to: 'kQD6oPnzaaAMRW24R8F0_nlSsJQni0cGHntR027eT9_sgtwt',
value: '0.01',
extracurrency: { 100: BigInt(10 ** 6) },
body: 'Hello extra currency v4'
})]
});
// Perform transfer
await contract.send(transfer);
// Awaiting update
await (0, testWallets_1.tillNextSeqno)(contract, seqno);
});
});