-
Notifications
You must be signed in to change notification settings - Fork 1
/
HighloadWalletV2.ts
157 lines (142 loc) · 4.48 KB
/
HighloadWalletV2.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
import {
Address,
beginCell,
Cell,
Contract,
contractAddress,
ContractProvider,
internal,
MessageRelaxed,
Sender,
SendMode,
Dictionary,
} from "@ton/core";
import { Maybe } from "@ton/core/dist/utils/maybe";
import { HighloadWalletDictionaryValue } from "./types/HighloadWalletDictionaryValue";
import { createHighloadWalletTransferV2 } from "./signing/createWalletTransfer";
export class HighloadWalletContractV2 implements Contract {
/**
* Create instance
*/
static create(args: { workchain: number, publicKey: Buffer, walletId?: Maybe<number> }) {
return new HighloadWalletContractV2(args.workchain, args.publicKey, args.walletId);
}
/**
* Generate query id
*/
static generateQueryId(timeout: number, randomId?: number) {
const now = Math.floor(Date.now() / 1000);
const random = randomId || Math.floor(Math.random() * Math.pow(2, 30));
return (BigInt(now + timeout) << 32n) | BigInt(random);
}
readonly workchain: number;
readonly publicKey: Buffer;
readonly address: Address;
readonly walletId: number;
readonly init: { data: Cell, code: Cell };
private constructor(workchain: number, publicKey: Buffer, walletId?: Maybe<number>) {
// Resolve parameters
this.workchain = workchain;
this.publicKey = publicKey;
if (walletId !== null && walletId !== undefined) {
this.walletId = walletId;
} else {
this.walletId = 698983191 + workchain; // ask this code
}
// Build initial code and data
const code = Cell.fromBoc(Buffer.from("B5EE9C724101090100E5000114FF00F4A413F4BCF2C80B010201200203020148040501EAF28308D71820D31FD33FF823AA1F5320B9F263ED44D0D31FD33FD3FFF404D153608040F40E6FA131F2605173BAF2A207F901541087F910F2A302F404D1F8007F8E16218010F4786FA5209802D307D43001FB009132E201B3E65B8325A1C840348040F4438AE63101C8CB1F13CB3FCBFFF400C9ED54080004D03002012006070017BD9CE76A26869AF98EB85FFC0041BE5F976A268698F98E99FE9FF98FA0268A91040207A0737D098C92DBFC95DD1F140034208040F4966FA56C122094305303B9DE2093333601926C21E2B39F9E545A", "hex"))[0];
const data = beginCell()
.storeUint(this.walletId, 32) // subwallet_id
.storeUint(0, 64) // last_cleaned
.storeBuffer(this.publicKey) // public_key
.storeDict(Dictionary.empty(Dictionary.Keys.Int(16), HighloadWalletDictionaryValue)) // old_queries
.endCell();
this.init = { code, data };
this.address = contractAddress(workchain, { code, data });
}
/**
* Get wallet balance
*/
async getBalance(provider: ContractProvider) {
const state = await provider.getState();
return state.balance;
}
/**
* Get wallet public key
*/
async getPublicKey(provider: ContractProvider) {
const result = await provider.get("get_public_key", []);
return result.stack.readBigNumber().toString(16);
}
/**
* Get tx status
*/
async getProcessed(provider: ContractProvider, queryId: bigint) {
const result = await provider.get("processed?", [{
type: "int",
value: queryId,
}]);
return result.stack.readBoolean();
}
/**
* Send signed transfer
*/
async send(provider: ContractProvider, message: Cell) {
await provider.external(message);
}
/**
* Sign and send transfer
*/
async sendTransfer(provider: ContractProvider, args: {
secretKey: Buffer,
messages: MessageRelaxed[],
sendMode?: Maybe<SendMode>,
timeout?: Maybe<number>
}) {
const { body, queryId } = this.createTransfer(args);
await this.send(provider, body);
return queryId;
}
/**
* Create transfer
*/
createTransfer(args: {
secretKey: Buffer,
messages: MessageRelaxed[],
sendMode?: Maybe<SendMode>,
timeout?: Maybe<number>,
}) {
let sendMode = SendMode.PAY_GAS_SEPARATELY;
if (args.sendMode !== null && args.sendMode !== undefined) {
sendMode = args.sendMode;
}
return createHighloadWalletTransferV2({
sendMode,
secretKey: args.secretKey,
messages: args.messages,
walletId: this.walletId,
timeout: args.timeout,
});
}
/**
* Create sender
*/
sender(provider: ContractProvider, secretKey: Buffer): Sender {
return {
send: async (args) => {
const { body } = this.createTransfer({
secretKey,
sendMode: args.sendMode,
messages: [internal({
to: args.to,
value: args.value,
init: args.init,
body: args.body,
bounce: args.bounce
})]
});
await this.send(provider, body);
}
};
}
}