Skip to content

Commit 2c78252

Browse files
committed
Support all actions from block.tlb
Add reserve_currecy, change_library. Add reserve modes and lib ref as they are needed.
1 parent e0ed819 commit 2c78252

File tree

5 files changed

+340
-34
lines changed

5 files changed

+340
-34
lines changed

src/types/LibRef.ts

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/**
2+
* Copyright (c) Whales Corp.
3+
* All Rights Reserved.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
import { Builder } from "../boc/Builder";
10+
import { Cell } from "../boc/Cell";
11+
import { Slice } from "../boc/Slice";
12+
13+
// Source: https://github.com/ton-blockchain/ton/blob/128a85bee568e84146f1e985a92ea85011d1e380/crypto/block/block.tlb#L385-L386
14+
// libref_hash$0 lib_hash:bits256 = LibRef;
15+
// libref_ref$1 library:^Cell = LibRef;
16+
17+
18+
export interface LibRefHash {
19+
type: 'hash';
20+
libHash: Buffer;
21+
}
22+
23+
export interface LibRefRef {
24+
type: 'ref';
25+
library: Cell;
26+
}
27+
28+
export type LibRef = LibRefHash | LibRefRef;
29+
30+
export function loadLibRef(slice: Slice): LibRef {
31+
const type = slice.loadUint(1);
32+
if (type === 0) {
33+
return {
34+
type: 'hash',
35+
libHash: slice.loadBuffer(32)
36+
};
37+
}
38+
else {
39+
return {
40+
type: 'ref',
41+
library: slice.loadRef()
42+
};
43+
}
44+
}
45+
46+
export function storeLibRef(src: LibRef) {
47+
return (builder: Builder) => {
48+
if (src.type === 'hash') {
49+
builder.storeUint(0, 1);
50+
builder.storeBuffer(src.libHash);
51+
}
52+
else {
53+
builder.storeUint(1, 1);
54+
builder.storeRef(src.library);
55+
}
56+
}
57+
}
58+

src/types/OutList.spec.ts

+185-32
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,18 @@ import {
1111
loadOutAction,
1212
loadOutList,
1313
OutAction,
14+
OutActionChangeLibrary,
15+
OutActionReserve,
1416
OutActionSendMsg,
1517
OutActionSetCode,
1618
storeOutAction,
1719
storeOutList
1820
} from "./OutList";
1921
import {SendMode} from "./SendMode";
2022
import {MessageRelaxed, storeMessageRelaxed} from "./MessageRelaxed";
23+
import { ReserveMode } from "./ReserveMode";
24+
import { storeCurrencyCollection } from "./CurrencyCollection";
25+
import { LibRef, storeLibRef } from "./LibRef";
2126

2227
const mockMessageRelaxed1: MessageRelaxed = {
2328
info: {
@@ -48,6 +53,8 @@ const mockSetCodeCell = beginCell().storeUint(123, 8).endCell();
4853
describe('Out List', () => {
4954
const outActionSendMsgTag = 0x0ec3c86d;
5055
const outActionSetCodeTag = 0xad4de08e;
56+
const outActionReserveTag = 0x36e6b809;
57+
const outActionChangeLibraryTag = 0x26fa1dd4;
5158

5259
it('Should serialise sendMsg action', () => {
5360
const mode = SendMode.PAY_GAS_SEPARATELY;
@@ -82,6 +89,44 @@ describe('Out List', () => {
8289
expect(expected.equals(actual)).toBeTruthy();
8390
});
8491

92+
it('Should serialize reserve action', () => {
93+
const mode = ReserveMode.AT_MOST_THIS_AMOUNT;
94+
const currency = { coins: 2000000n }
95+
const action = storeOutAction({
96+
type: 'reserve',
97+
mode,
98+
currency
99+
});
100+
101+
const actual = beginCell().store(action).endCell();
102+
103+
const expected = beginCell()
104+
.storeUint(outActionReserveTag, 32)
105+
.storeUint(mode, 8)
106+
.store(storeCurrencyCollection(currency))
107+
.endCell();
108+
109+
expect(expected.equals(actual)).toBeTruthy();
110+
});
111+
112+
it('Should serialize changeLibrary action', () => {
113+
const mode = 0;
114+
const lib = beginCell().storeUint(1234, 16).endCell();
115+
const libRef: LibRef = { type: "ref", library: lib };
116+
const action = storeOutAction({
117+
type: 'changeLibrary',
118+
mode,
119+
libRef
120+
});
121+
const actual = beginCell().store(action).endCell();
122+
const expected = beginCell()
123+
.storeUint(outActionChangeLibraryTag, 32)
124+
.storeUint(mode, 7)
125+
.store(storeLibRef(libRef))
126+
.endCell();
127+
expect(expected.equals(actual)).toBeTruthy();
128+
});
129+
85130
it('Should deserialize sendMsg action', () => {
86131
const mode = SendMode.PAY_GAS_SEPARATELY;
87132
const action = beginCell()
@@ -122,9 +167,52 @@ describe('Out List', () => {
122167
expect(expected.newCode.equals(actual.newCode)).toBeTruthy();
123168
});
124169

170+
it('Should deserialize reserve action', () => {
171+
const mode = ReserveMode.THIS_AMOUNT;
172+
const currency = { coins: 3000000n }
173+
const action = beginCell()
174+
.storeUint(outActionReserveTag, 32)
175+
.storeUint(mode, 8)
176+
.store(storeCurrencyCollection(currency))
177+
.endCell();
178+
179+
const actual = loadOutAction(action.beginParse()) as OutActionReserve;
180+
181+
const expected = {
182+
type: 'reserve',
183+
mode,
184+
currency
185+
};
186+
expect(expected.type).toEqual(actual.type);
187+
expect(expected.mode).toEqual(actual.mode);
188+
expect(expected.currency.coins).toEqual(actual.currency.coins);
189+
});
190+
191+
it('Should deserialize changeLibrary action', () => {
192+
const mode = 1;
193+
const libHash = Buffer.alloc(32);
194+
const libRef: LibRef = { type: "hash", libHash};
195+
const action = beginCell()
196+
.storeUint(outActionChangeLibraryTag, 32)
197+
.storeUint(mode, 7)
198+
.store(storeLibRef(libRef))
199+
.endCell();
200+
const actual = loadOutAction(action.beginParse()) as OutActionChangeLibrary;
201+
const expected = {
202+
type: 'changeLibrary',
203+
mode,
204+
libRef
205+
};
206+
expect(expected.type).toEqual(actual.type);
207+
expect(expected.mode).toEqual(actual.mode);
208+
expect(expected.libRef).toEqual(actual.libRef);
209+
});
210+
125211
it('Should serialize out list', () => {
212+
const reserveMode = ReserveMode.THIS_AMOUNT;
126213
const sendMode1 = SendMode.PAY_GAS_SEPARATELY;
127214
const sendMode2 = SendMode.IGNORE_ERRORS;
215+
const changeLibraryMode = 1;
128216

129217
const actions: OutAction[] = [
130218
{
@@ -140,44 +228,77 @@ describe('Out List', () => {
140228
{
141229
type: 'setCode',
142230
newCode: mockSetCodeCell
231+
},
232+
{
233+
type: 'reserve',
234+
mode: reserveMode,
235+
currency: {
236+
coins: 3000000n
237+
}
238+
},
239+
{
240+
type: 'changeLibrary',
241+
mode: changeLibraryMode,
242+
libRef: {
243+
type: "ref",
244+
library: beginCell().storeUint(1234, 16).endCell()
245+
}
143246
}
144247
]
145248

146249
const actual = beginCell().store(storeOutList(actions)).endCell();
147250

148251
// tvm handles actions from c5 in reversed order
149252
const expected =
150-
beginCell()
151-
.storeRef(
152-
beginCell()
153-
.storeRef(
154-
beginCell()
155-
.storeRef(beginCell().endCell())
156-
.storeUint(outActionSendMsgTag, 32)
157-
.storeUint(sendMode1, 8)
158-
.storeRef(beginCell().store(storeMessageRelaxed(mockMessageRelaxed1)).endCell())
159-
.endCell()
160-
)
161-
.storeUint(outActionSendMsgTag, 32)
162-
.storeUint(sendMode2, 8)
163-
.storeRef(beginCell().store(storeMessageRelaxed(mockMessageRelaxed2)).endCell())
164-
.endCell()
165-
)
166-
.storeUint(outActionSetCodeTag, 32)
167-
.storeRef(mockSetCodeCell)
168-
.endCell()
169-
170-
253+
beginCell()
254+
.storeRef(
255+
beginCell()
256+
.storeRef(
257+
beginCell()
258+
.storeRef(
259+
beginCell()
260+
.storeRef(
261+
beginCell()
262+
.storeRef(beginCell().endCell())
263+
.storeUint(outActionSendMsgTag, 32)
264+
.storeUint(sendMode1, 8)
265+
.storeRef(beginCell().store(storeMessageRelaxed(mockMessageRelaxed1)).endCell())
266+
.endCell()
267+
)
268+
.storeUint(outActionSendMsgTag, 32)
269+
.storeUint(sendMode2, 8)
270+
.storeRef(beginCell().store(storeMessageRelaxed(mockMessageRelaxed2)).endCell())
271+
.endCell()
272+
)
273+
.storeUint(outActionSetCodeTag, 32)
274+
.storeRef(mockSetCodeCell)
275+
.endCell()
276+
)
277+
.storeUint(outActionReserveTag, 32)
278+
.storeUint(reserveMode, 8)
279+
.store(storeCurrencyCollection({ coins: 3000000n }))
280+
.endCell()
281+
)
282+
.storeUint(outActionChangeLibraryTag, 32)
283+
.storeUint(changeLibraryMode, 7)
284+
.store(storeLibRef({
285+
type: "ref",
286+
library: beginCell().storeUint(1234, 16).endCell()
287+
}))
288+
.endCell();
171289

172290
expect(actual.equals(expected)).toBeTruthy();
173291
});
174292

175293
it('Should deserialize out list', () => {
176294
const outActionSendMsgTag = 0x0ec3c86d;
177295
const outActionSetCodeTag = 0xad4de08e;
296+
const outActionReserveTag = 0x36e6b809;
178297

179298
const sendMode1 = SendMode.PAY_GAS_SEPARATELY;
180299
const sendMode2 = SendMode.IGNORE_ERRORS;
300+
const reserveMode = ReserveMode.THIS_AMOUNT;
301+
const changeLibraryMode = 1;
181302

182303
const expected: OutAction[] = [
183304
{
@@ -193,7 +314,23 @@ describe('Out List', () => {
193314
{
194315
type: 'setCode',
195316
newCode: mockSetCodeCell
317+
},
318+
{
319+
type: 'reserve',
320+
mode: reserveMode,
321+
currency: {
322+
coins: 3000000n
323+
}
324+
},
325+
{
326+
type: 'changeLibrary',
327+
mode: changeLibraryMode,
328+
libRef: {
329+
type: "ref",
330+
library: beginCell().storeUint(1234, 16).endCell()
331+
}
196332
}
333+
197334
]
198335

199336
const rawList =
@@ -202,20 +339,37 @@ describe('Out List', () => {
202339
beginCell()
203340
.storeRef(
204341
beginCell()
205-
.storeRef(beginCell().endCell())
206-
.storeUint(outActionSendMsgTag, 32)
207-
.storeUint(sendMode1, 8)
208-
.storeRef(beginCell().store(storeMessageRelaxed(mockMessageRelaxed1)).endCell())
342+
.storeRef(
343+
beginCell()
344+
.storeRef(
345+
beginCell()
346+
.storeRef(beginCell().endCell())
347+
.storeUint(outActionSendMsgTag, 32)
348+
.storeUint(sendMode1, 8)
349+
.storeRef(beginCell().store(storeMessageRelaxed(mockMessageRelaxed1)).endCell())
350+
.endCell()
351+
)
352+
.storeUint(outActionSendMsgTag, 32)
353+
.storeUint(sendMode2, 8)
354+
.storeRef(beginCell().store(storeMessageRelaxed(mockMessageRelaxed2)).endCell())
355+
.endCell()
356+
)
357+
.storeUint(outActionSetCodeTag, 32)
358+
.storeRef(mockSetCodeCell)
209359
.endCell()
210360
)
211-
.storeUint(outActionSendMsgTag, 32)
212-
.storeUint(sendMode2, 8)
213-
.storeRef(beginCell().store(storeMessageRelaxed(mockMessageRelaxed2)).endCell())
361+
.storeUint(outActionReserveTag, 32)
362+
.storeUint(reserveMode, 8)
363+
.store(storeCurrencyCollection({ coins: 3000000n }))
214364
.endCell()
215365
)
216-
.storeUint(outActionSetCodeTag, 32)
217-
.storeRef(mockSetCodeCell)
218-
.endCell()
366+
.storeUint(outActionChangeLibraryTag, 32)
367+
.storeUint(changeLibraryMode, 7)
368+
.store(storeLibRef({
369+
type: "ref",
370+
library: beginCell().storeUint(1234, 16).endCell()
371+
}))
372+
.endCell();
219373

220374
const actual = loadOutList(rawList.beginParse());
221375

@@ -235,6 +389,5 @@ describe('Out List', () => {
235389
expect(item1.newCode.equals(item2.newCode)).toBeTruthy();
236390
}
237391
})
238-
239392
});
240393
});

0 commit comments

Comments
 (0)