@ton.js/core
Version:
TonWeb - JavaScript API for TON blockchain
174 lines • 6.81 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.WalletContract = void 0;
const bn_js_1 = __importDefault(require("bn.js"));
const tweetnacl_1 = __importDefault(require("tweetnacl"));
const contract_1 = require("../contract");
const cell_1 = require("../../boc/cell");
const address_1 = require("../../utils/address");
/**
* Abstract standard wallet class.
*/
class WalletContract extends contract_1.Contract {
constructor(provider, options) {
if (!options.publicKey && !options.address) {
throw new Error(`Missing "publicKey" or "address" options`);
}
super(provider, options);
this.methods = {
transfer: (params) => contract_1.Contract.createMethod(provider, this.createTransferMessage(params.secretKey, params.toAddress, params.amount, params.seqno, params.payload, params.sendMode, !Boolean(params.secretKey), params.stateInit)),
seqno: () => ({
// @todo: we do we have sub-method here?
// should we rename `seqno` to `getSeqno`
// and return the result directly?
call: async () => {
const address = await this.getAddress();
let seqno;
try {
seqno = (await provider.call2(address.toString(), 'seqno')).toNumber();
}
catch (error) {
// Ignoring the error
// @todo: it doesn't look like a
// good idea to silently ignore
// the errors
}
return seqno;
}
})
};
}
/**
* Returns name of the contract.
*/
getName() {
// This method should be implemented in the subclasses
throw new Error('Not implemented');
}
/**
* Creates external message for contract initialization.
*/
async createInitExternalMessage(secretKey) {
// @todo: we should return ExternalMessage instead of Query
// but we will need to add `signature` to the result
if (!this.options.publicKey) {
const keyPair = tweetnacl_1.default.sign.keyPair.fromSecretKey(secretKey);
this.options.publicKey = keyPair.publicKey;
}
const { stateInit, address, code, data, } = await this.createStateInit();
const signingMessage = this.createSigningMessage();
const signature = tweetnacl_1.default.sign.detached(await signingMessage.hash(), secretKey);
const body = new cell_1.Cell();
body.bits.writeBytes(signature);
body.writeCell(signingMessage);
const header = contract_1.Contract.createExternalMessageHeader(address);
const externalMessage = contract_1.Contract.createCommonMsgInfo(header, stateInit, body);
return {
address,
message: externalMessage,
body,
signingMessage,
stateInit,
code,
data,
};
}
async createTransferMessage(
/**
* `nacl.KeyPair.secretKey`
* @todo: improve the description
*/
secretKey, address, nanograms, seqno, payload, sendMode = 3, dummySignature = false, stateInit) {
const payloadCell = this.serializePayload(payload);
const orderHeader = contract_1.Contract.createInternalMessageHeader(new address_1.Address(address), new bn_js_1.default(nanograms));
const order = contract_1.Contract.createCommonMsgInfo(orderHeader, stateInit, payloadCell);
const signingMessage = this.createSigningMessage(seqno);
signingMessage.bits.writeUint8(sendMode);
signingMessage.refs.push(order);
return this.createExternalMessage(signingMessage, secretKey, seqno, dummySignature);
}
deploy(secretKey) {
return contract_1.Contract.createMethod(this.provider, this.createInitExternalMessage(secretKey));
}
/**
* Returns cell that contains wallet data.
*/
createDataCell() {
// 4 byte seqno, 32 byte publicKey
const cell = new cell_1.Cell();
cell.bits.writeUint(0, 32); // seqno
cell.bits.writeBytes(this.options.publicKey);
return cell;
}
createSigningMessage(seqno) {
seqno = (seqno || 0);
const cell = new cell_1.Cell();
cell.bits.writeUint(seqno, 32);
return cell;
}
async createExternalMessage(signingMessage,
/**
* `nacl.KeyPair.secretKey`
* @todo: improve the description
*/
secretKey, seqno, dummySignature = false) {
const signature = (dummySignature
? new Uint8Array(64)
: tweetnacl_1.default.sign.detached(await signingMessage.hash(), secretKey));
const body = new cell_1.Cell();
body.bits.writeBytes(signature);
body.writeCell(signingMessage);
let stateInit;
let code;
let data;
if (seqno === 0) {
if (!this.options.publicKey) {
const keyPair = (tweetnacl_1.default.sign.keyPair
.fromSecretKey(secretKey));
this.options.publicKey = keyPair.publicKey;
}
const deploy = await this.createStateInit();
stateInit = deploy.stateInit;
code = deploy.code;
data = deploy.data;
}
const selfAddress = await this.getAddress();
const header = contract_1.Contract.createExternalMessageHeader(selfAddress);
const resultMessage = contract_1.Contract.createCommonMsgInfo(header, stateInit, body);
return {
address: selfAddress,
signature,
// old wallet_send_generate_external_message
message: resultMessage,
body,
signingMessage,
stateInit,
code,
data,
};
}
serializePayload(payload) {
if (!payload) {
return new cell_1.Cell();
}
if (payload instanceof cell_1.Cell) {
return payload;
}
let payloadCell = new cell_1.Cell();
// @todo: throw more meaningful error
// on cell bytes overflow
if (typeof payload === 'string') {
payloadCell.bits.writeUint(0, 32);
payloadCell.bits.writeString(payload);
}
else {
payloadCell.bits.writeBytes(payload);
}
return payloadCell;
}
}
exports.WalletContract = WalletContract;
//# sourceMappingURL=wallet-contract.js.map