forked from ton-blockchain/token-contract
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathJettonMinter.ts
167 lines (148 loc) · 6.66 KB
/
JettonMinter.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
158
159
160
161
162
163
164
165
166
167
import { Address, beginCell, Cell, Contract, contractAddress, ContractProvider, Sender, SendMode, toNano, internal as internal_relaxed, storeMessageRelaxed } from '@ton/core';
import { Op } from './JettonConstants';
export type JettonMinterContent = {
type:0|1,
uri:string
};
export type JettonMinterConfig = {admin: Address; content: Cell; wallet_code: Cell};
export function jettonMinterConfigToCell(config: JettonMinterConfig): Cell {
return beginCell()
.storeCoins(0)
.storeAddress(config.admin)
.storeRef(config.content)
.storeRef(config.wallet_code)
.endCell();
}
export function jettonContentToCell(content:JettonMinterContent) {
return beginCell()
.storeUint(content.type, 8)
.storeStringTail(content.uri) //Snake logic under the hood
.endCell();
}
export class JettonMinter implements Contract {
constructor(readonly address: Address, readonly init?: { code: Cell; data: Cell }) {}
static createFromAddress(address: Address) {
return new JettonMinter(address);
}
static createFromConfig(config: JettonMinterConfig, code: Cell, workchain = 0) {
const data = jettonMinterConfigToCell(config);
const init = { code, data };
return new JettonMinter(contractAddress(workchain, init), init);
}
async sendDeploy(provider: ContractProvider, via: Sender, value: bigint) {
await provider.internal(via, {
value,
sendMode: SendMode.PAY_GAS_SEPARATELY,
body: beginCell().endCell(),
});
}
protected static jettonInternalTransfer(jetton_amount: bigint,
forward_ton_amount: bigint,
response_addr?: Address,
query_id: number | bigint = 0) {
return beginCell()
.storeUint(Op.internal_transfer, 32)
.storeUint(query_id, 64)
.storeCoins(jetton_amount)
.storeAddress(null)
.storeAddress(response_addr)
.storeCoins(forward_ton_amount)
.storeBit(false)
.endCell();
}
static mintMessage(from: Address, to: Address, jetton_amount: bigint, forward_ton_amount: bigint, total_ton_amount: bigint, query_id: number | bigint = 0) {
const mintMsg = beginCell().storeUint(Op.internal_transfer, 32)
.storeUint(0, 64)
.storeCoins(jetton_amount)
.storeAddress(null)
.storeAddress(from) // Response addr
.storeCoins(forward_ton_amount)
.storeMaybeRef(null)
.endCell();
return beginCell().storeUint(Op.mint, 32).storeUint(query_id, 64) // op, queryId
.storeAddress(to)
.storeCoins(total_ton_amount)
.storeCoins(jetton_amount)
.storeRef(mintMsg)
.endCell();
}
async sendMint(provider: ContractProvider, via: Sender, to: Address, jetton_amount: bigint, forward_ton_amount: bigint, total_ton_amount: bigint) {
if(total_ton_amount <= forward_ton_amount) {
throw new Error("Total ton amount should be > forward amount");
}
await provider.internal(via, {
sendMode: SendMode.PAY_GAS_SEPARATELY,
body: JettonMinter.mintMessage(this.address, to, jetton_amount, forward_ton_amount, total_ton_amount),
value: total_ton_amount + toNano('0.015'),
});
}
/* provide_wallet_address#2c76b973 query_id:uint64 owner_address:MsgAddress include_address:Bool = InternalMsgBody;
*/
static discoveryMessage(owner: Address, include_address: boolean) {
return beginCell().storeUint(0x2c76b973, 32).storeUint(0, 64) // op, queryId
.storeAddress(owner).storeBit(include_address)
.endCell();
}
async sendDiscovery(provider: ContractProvider, via: Sender, owner: Address, include_address: boolean, value:bigint = toNano('0.1')) {
await provider.internal(via, {
sendMode: SendMode.PAY_GAS_SEPARATELY,
body: JettonMinter.discoveryMessage(owner, include_address),
value: value,
});
}
static changeAdminMessage(newOwner: Address) {
return beginCell().storeUint(Op.change_admin, 32).storeUint(0, 64) // op, queryId
.storeAddress(newOwner)
.endCell();
}
async sendChangeAdmin(provider: ContractProvider, via: Sender, newOwner: Address) {
await provider.internal(via, {
sendMode: SendMode.PAY_GAS_SEPARATELY,
body: JettonMinter.changeAdminMessage(newOwner),
value: toNano("0.05"),
});
}
static changeContentMessage(content: Cell) {
return beginCell().storeUint(Op.change_content, 32).storeUint(0, 64) // op, queryId
.storeRef(content)
.endCell();
}
async sendChangeContent(provider: ContractProvider, via: Sender, content: Cell) {
await provider.internal(via, {
sendMode: SendMode.PAY_GAS_SEPARATELY,
body: JettonMinter.changeContentMessage(content),
value: toNano("0.05"),
});
}
async getWalletAddress(provider: ContractProvider, owner: Address): Promise<Address> {
const res = await provider.get('get_wallet_address', [{ type: 'slice', cell: beginCell().storeAddress(owner).endCell() }])
return res.stack.readAddress()
}
async getJettonData(provider: ContractProvider) {
let res = await provider.get('get_jetton_data', []);
let totalSupply = res.stack.readBigNumber();
let mintable = res.stack.readBoolean();
let adminAddress = res.stack.readAddress();
let content = res.stack.readCell();
let walletCode = res.stack.readCell();
return {
totalSupply,
mintable,
adminAddress,
content,
walletCode
};
}
async getTotalSupply(provider: ContractProvider) {
let res = await this.getJettonData(provider);
return res.totalSupply;
}
async getAdminAddress(provider: ContractProvider) {
let res = await this.getJettonData(provider);
return res.adminAddress;
}
async getContent(provider: ContractProvider) {
let res = await this.getJettonData(provider);
return res.content;
}
}