Skip to content

Commit 87d6682

Browse files
committed
fix and add readme
1 parent af0f869 commit 87d6682

14 files changed

+372
-192
lines changed

package-lock.json

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"typescript": "^4.7.4"
1616
},
1717
"dependencies": {
18+
"@ton.org/func-js": "^0.1.3",
1819
"@types/uuid": "^8.3.4",
1920
"bn.js": "^5.2.1",
2021
"chai": "^4.3.6",

packages/contracts/nft-raffle/main.test.ts

+136-71
Large diffs are not rendered by default.

packages/contracts/nft-raffle/raffle.local.ts

+16-22
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { SmartContract } from 'ton-contract-executor'
44
import { encodeRaffleStorage, RaffleStorage } from './raffle.storage'
55
import * as fs from 'fs'
66
import BN from 'bn.js'
7+
import { compileFunc } from "../../utils/compileFunc";
8+
import { RaffleSource } from './raffle.source'
79

810

911

@@ -21,12 +23,15 @@ type StateResponse = {
2123
leftCoinsGot: BN,
2224
rightCoinsGot: BN,
2325
coinsForNft: BN,
24-
leftNfts: Map<string, boolean> | null,
25-
rightNfts: Map<string, boolean> | null,
26+
nfts: Map<string, number> | null,
2627
raffledNfts: Map<string, boolean> | null
2728
}
2829

29-
function DictToMap (slice : Slice): boolean {
30+
function DictToMapN (slice : Slice): number {
31+
return slice.readUint(4).toNumber().valueOf()
32+
}
33+
34+
function DictToMapB (slice: Slice): boolean {
3035
return slice.readBit()
3136
}
3237

@@ -47,23 +52,18 @@ export class RaffleLocal {
4752
const [ state, rightNftsCount, rightNftsReceived, leftNftsCount,
4853
leftNftsReceived, leftUser, rightUser, superUser, leftCommission,
4954
rightCommission, leftCoinsGot, rightCoinsGot,
50-
coinsForNft, leftNfts, rightNfts, raffledNfts ] = res.result as [BN, BN,
55+
coinsForNft, nfts, raffledNfts ] = res.result as [BN, BN,
5156
BN, BN,
5257
BN, Slice, Slice, Slice, BN, BN, BN, BN, BN, Cell, Cell, Cell]
53-
const leftMap = leftNfts ? parseDict<boolean>(
54-
leftNfts.beginParse(),
55-
256,
56-
DictToMap
57-
) : null
58-
const rightMap = rightNfts ? parseDict<boolean>(
59-
rightNfts.beginParse(),
58+
const nftMap = nfts ? parseDict<number>(
59+
nfts.beginParse(),
6060
256,
61-
DictToMap
61+
DictToMapN
6262
) : null
6363
const raffledMap = raffledNfts ? parseDict<boolean>(
6464
raffledNfts.beginParse(),
6565
256,
66-
DictToMap
66+
DictToMapB
6767
) : null
6868
return {
6969
state: state ? state.toNumber() : 0,
@@ -79,21 +79,15 @@ export class RaffleLocal {
7979
leftCoinsGot: leftCoinsGot,
8080
rightCoinsGot: rightCoinsGot,
8181
coinsForNft: coinsForNft,
82-
leftNfts: leftMap,
83-
rightNfts: rightMap,
82+
nfts: nftMap,
8483
raffledNfts: raffledMap
8584
}
8685
}
8786

88-
static bocFileToTCell (filename: string): Cell {
89-
const file = fs.readFileSync(filename)
90-
return Cell.fromBoc(file)[0]
91-
}
92-
9387
static async createFromConfig(raffleStorage: RaffleStorage) {
94-
const code = RaffleLocal.bocFileToTCell('./packages/contracts/sources/nft-raffle/code.boc')
88+
const code = await compileFunc(RaffleSource)
9589
const data = encodeRaffleStorage(raffleStorage)
96-
const smc = await SmartContract.fromCell(code, data)
90+
const smc = await SmartContract.fromCell(code.cell, data)
9791

9892
const address = contractAddress({
9993
workchain: 0,

packages/contracts/nft-raffle/raffle.queries.ts

+29-26
Original file line numberDiff line numberDiff line change
@@ -3,47 +3,50 @@ import BN from 'bn.js'
33
import { SmartContract } from 'ton-contract-executor'
44
import { getRandSigner } from './raffle.signers'
55

6-
class queries {
7-
public static nftOwnerAssigned (
8-
queryId: BN,
9-
prevOwner: Address,
10-
op: number = 0x05138d91
11-
): Cell {
12-
const msg = new Builder()
13-
.storeUint(op, 32)
14-
.storeUint(queryId, 64)
15-
.storeAddress(prevOwner)
16-
.storeBit(0)
6+
export const OperationCodes = {
7+
ownershipAssigned: 0x05138d91,
8+
cancel: 2001,
9+
addCoins: 2002,
10+
maintain: 2003,
11+
sendAgain: 2004,
12+
}
1713

18-
return msg.endCell()
19-
}
14+
export const Queries = {
15+
nftOwnerAssigned: (params: { queryId?: number, prevOwner: Address}) => {
16+
const msgBody = new Cell()
17+
msgBody.bits.writeUint(OperationCodes.ownershipAssigned, 32)
18+
msgBody.bits.writeUint(params.queryId || 0, 64)
19+
msgBody.bits.writeAddress(params.prevOwner)
2020

21-
public static cancel (): Cell {
21+
return msgBody
22+
},
23+
cancel: () => {
2224
const msg = new Builder()
23-
.storeUint(2001, 32)
24-
25+
.storeUint(OperationCodes.cancel, 32)
2526
return msg.endCell()
26-
}
27-
28-
public static addCoins (): Cell {
27+
},
28+
addCoins: () => {
2929
const msg = new Builder()
30-
.storeUint(2002, 32)
30+
.storeUint(OperationCodes.addCoins, 32)
3131
return msg.endCell()
32-
}
33-
34-
public static sendTrans (): Cell {
32+
},
33+
sendTrans: () => {
3534
const body = new Builder()
3635
.storeUint(0x18, 6)
3736
.storeAddress(getRandSigner())
3837
.storeCoins(toNano(0.1))
3938
.storeUint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)
4039
const msg = new Builder()
41-
.storeUint(2003, 32)
40+
.storeUint(OperationCodes.maintain, 32)
4241
.storeRef(body.endCell())
4342
.storeUint(0, 8)
4443
.endCell()
4544
return msg
45+
},
46+
sendAgain: () => {
47+
const msg = new Builder()
48+
.storeUint(OperationCodes.sendAgain, 32)
49+
.endCell()
50+
return msg
4651
}
4752
}
48-
49-
export { queries }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { combineFunc } from "../../utils/combineFunc";
2+
3+
4+
export const RaffleSource = combineFunc(__dirname, [
5+
"../sources/stdlib.fc",
6+
"../sources/nft-raffle/struct/constants.func",
7+
"../sources/nft-raffle/struct/storage.func",
8+
"../sources/nft-raffle/struct/utils.func",
9+
"../sources/nft-raffle/struct/handles.func",
10+
"../sources/nft-raffle/struct/get-methods.func",
11+
'../sources/nft-raffle/main.func',
12+
])

packages/contracts/nft-raffle/raffle.storage.ts

+12-20
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,16 @@ interface CommissionSlice {
2323
leftCommission: BN
2424
rightCommission: BN
2525
coinsForNft: BN
26+
coinsForCommission: BN
2627
}
2728

28-
interface NFTItem {
29+
export interface NFTItem {
2930
addr: Address
30-
received: boolean
31+
received: number
3132
}
3233

3334
interface DictSlice {
34-
leftNfts: NFTItem[]
35-
rightNfts: NFTItem[]
35+
nfts: NFTItem[]
3636
}
3737

3838
export interface RaffleStorage {
@@ -64,26 +64,18 @@ function encodeRaffleStorage
6464
.storeCoins(new BN(0))
6565
.storeCoins(new BN(0))
6666
.storeCoins(raffleStorage.commissionSlice.coinsForNft)
67+
.storeCoins(raffleStorage.commissionSlice.coinsForCommission)
6768
.endCell()
68-
const leftNfts = new DictBuilder(256)
69-
if (raffleStorage.dictSlice.leftNfts.length > 0) {
70-
for (let i = 0; i < raffleStorage.dictSlice.leftNfts.length; i += 1) {
71-
const bitCell = new Cell()
72-
bitCell.bits.writeBit(raffleStorage.dictSlice.leftNfts[i].received)
73-
leftNfts.storeCell(new BN(raffleStorage.dictSlice.leftNfts[i].addr.hash), bitCell)
74-
}
75-
}
76-
const rightNfts = new DictBuilder(256)
77-
if (raffleStorage.dictSlice.rightNfts.length > 0) {
78-
for (let i = 0; i < raffleStorage.dictSlice.rightNfts.length; i += 1) {
79-
const bitCell = new Cell()
80-
bitCell.bits.writeBit(raffleStorage.dictSlice.rightNfts[i].received)
81-
rightNfts.storeCell(new BN(raffleStorage.dictSlice.rightNfts[i].addr.hash), bitCell)
69+
const nfts = new DictBuilder(256)
70+
if (raffleStorage.dictSlice.nfts.length > 0) {
71+
for (let i = 0; i < raffleStorage.dictSlice.nfts.length; i += 1) {
72+
const value = new Cell()
73+
value.bits.writeUint(raffleStorage.dictSlice.nfts[i].received, 4)
74+
nfts.storeCell(new BN(raffleStorage.dictSlice.nfts[i].addr.hash), value)
8275
}
8376
}
8477
const dictCell = new Builder()
85-
.storeDict(leftNfts.endCell())
86-
.storeDict(rightNfts.endCell())
78+
.storeDict(nfts.endCell())
8779
.storeDict(new DictBuilder(256).endDict())
8880
const storageCell = new Builder()
8981
.storeRef(stateCell)

packages/contracts/sources/nft-raffle/main.func

+5-6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,3 @@
1-
#include "../stdlib.fc";
2-
#include "struct/constants.func";
3-
#include "struct/storage.func";
4-
#include "struct/utils.func";
5-
#include "struct/handles.func";
6-
#include "struct/get-methods.func";
71

82

93
{-
@@ -49,6 +43,11 @@
4943
return ();
5044
}
5145

46+
if (op == op::send_again()) {
47+
handle::send_again(msg_value);
48+
return ();
49+
}
50+
5251
if (op == op::maintain()) {
5352
handle::maintain(sender_addr, in_msg_body);
5453
return();

packages/contracts/sources/nft-raffle/struct/constants.func

+3
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,19 @@ int state::canceled() asm "2 PUSHINT";
33
int state::completed() asm "3 PUSHINT";
44

55
int min_tons_for_storage() asm "1000000 PUSHINT"; ;; 0,001 TON
6+
int min_tons_for_operation() asm "10000000 PUSHINT"; ;; 0,01 TON
67

78
int op::transfer() asm "0x5fcc3d14 PUSHINT";
89
int op::ownership_assigned() asm "0x05138d91 PUSHINT";
910
int op::cancel() asm "2001 PUSHINT";
1011
int op::add_coins() asm "2002 PUSHINT";
1112
int op::maintain() asm "2003 PUSHINT";
13+
int op::send_again() asm "2004 PUSHINT";
1214

1315
slice msg::canceled() asm "<b 124 word NFT raffle canceled| $, b> <s PUSHSLICE";
1416
slice msg::commission() asm "<b 124 word NFT raffle commission| $, b> <s PUSHSLICE";
1517

1618

1719
int err::state() asm "1001 PUSHINT";
1820
int err::wrong_addr() asm "1002 PUSHINT";
21+
int err::coins() asm "1003 PUSHINT";

packages/contracts/sources/nft-raffle/struct/get-methods.func

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ _ raffle_state() method_id {
33
return (db::state, db::right_nfts_count, db::right_nfts_received, db::left_nfts_count,
44
db::left_nfts_received, db::left_user, db::right_user, db::super_user, db::left_commission,
55
db::right_commission, db::left_coins_got, db::right_coins_got, db::coins_for_nft,
6-
db::left_nfts, db::right_nfts, db::raffled_nfts);
6+
db::nfts, db::raffled_nfts);
77
}

packages/contracts/sources/nft-raffle/struct/handles.func

+22-15
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
() handle::raffle() impure inline_ref {
22
db::state = state::completed();
3-
db::raffled_nfts = utils::raffle_nfts(db::raffled_nfts, db::left_nfts, db::right_nfts);
3+
db::raffled_nfts = utils::raffle_nfts(db::raffled_nfts, db::nfts);
44
utils::send_raffled_nfts(db::raffled_nfts, db::coins_for_nft);
55
raw_reserve(min_tons_for_storage(), 0);
66
utils::send_tons(db::super_user, 0, msg::commission(), 130);
@@ -16,28 +16,27 @@
1616
}
1717

1818
() handle::receive_nft(slice nft_addr, int msg_value, slice in_msg_body) impure inline_ref {
19-
int extra_coins = msg_value - db::coins_for_nft;
20-
21-
if ((extra_coins < 0) | (db::state != state::active())) {
19+
int extra_coins = msg_value - db::coins_for_nft - db::coins_for_commission;
20+
21+
if ((extra_coins < min_tons_for_operation()) | (db::state != state::active())) {
2222
handle::return_nft(nft_addr,in_msg_body);
2323
return ();
2424
}
2525
(_, int addr) = parse_std_addr(nft_addr);
26-
(cell left_nfts, int left_succes) = db::left_nfts.utils::add_nft(addr);
27-
(cell right_nfts, int right_success) = db::right_nfts.utils::add_nft(addr);
26+
(cell nfts, int left_success, int right_success) = db::nfts.utils::add_nft(addr);
2827

29-
if (~ (left_succes | right_success)) {
28+
if (~ (left_success | right_success)) {
3029
handle::return_nft(nft_addr,in_msg_body);
3130
return ();
3231
}
33-
db::left_nfts = left_nfts;
34-
db::right_nfts = right_nfts;
35-
if (left_succes) {
32+
db::nfts = nfts;
33+
if (left_success) {
3634
db::left_nfts_received += 1;
37-
db::left_coins_got += msg_value;
38-
} else {
35+
db::left_coins_got += (db::coins_for_nft + db::coins_for_commission);
36+
}
37+
if(right_success) {
3938
db::right_nfts_received += 1;
40-
db::right_coins_got += msg_value;
39+
db::right_coins_got += (db::coins_for_nft + db::coins_for_commission);
4140
}
4241
if (utils::check_conditions()) {
4342
handle::raffle();
@@ -49,8 +48,7 @@
4948
throw_if(err::state(), db::state != state::active());
5049
throw_if(err::state(), utils::check_conditions());
5150
db::state = state::canceled();
52-
db::left_nfts.utils::send_nfts(db::coins_for_nft, db::left_user);
53-
db::right_nfts.utils::send_nfts(db::coins_for_nft, db::right_user);
51+
db::nfts.utils::send_nfts(db::coins_for_nft, db::left_user, db::right_user);
5452

5553
raw_reserve(min_tons_for_storage(), 0);
5654

@@ -75,6 +73,15 @@
7573
}
7674

7775
() handle::maintain(slice sender_addr, slice in_msg_body) impure inline_ref {
76+
throw_if(err::state(), db::state == state::active());
7877
throw_unless(err::wrong_addr(), equal_slices(sender_addr, db::super_user));
7978
send_raw_message(in_msg_body~load_ref(), in_msg_body~load_uint(8));
79+
}
80+
81+
() handle::send_again(int msg_value) impure inline_ref {
82+
throw_if(err::state(), db::state != state::completed());
83+
int need_coins = (db::left_nfts_count + db::right_nfts_count) * db::coins_for_nft;
84+
throw_if(err::coins(), msg_value < need_coins);
85+
int coins_for_nft = msg_value / (db::left_nfts_count + db::right_nfts_count);
86+
utils::send_raffled_nfts(db::raffled_nfts, coins_for_nft);
8087
}

0 commit comments

Comments
 (0)