|
|
|
import BN from "bn.js";
|
|
|
|
import {Address, beginCell, Cell, contractAddress, TonClient, WalletContract, WalletV3R2Source} from "ton";
|
|
|
|
import {mnemonicToWalletKey} from "ton-crypto";
|
|
|
|
|
|
|
|
// encode contract storage according to save_data() contract method
|
|
|
|
// storage#_ total_supply:Coins admin_address:MsgAddress next_admin_address:MsgAddress content:^Cell jetton_wallet_code:^Cell = Storage;
|
|
|
|
export function minterData(params: { adminAddress: Address; supply: number, nextAdminAddress?: Address, content: Cell, wallet_code: Cell }): Cell {
|
|
|
|
if (!params.nextAdminAddress) params.nextAdminAddress = params.adminAddress;
|
|
|
|
return beginCell()
|
|
|
|
.storeCoins(params.supply)
|
|
|
|
.storeAddress(params.adminAddress)
|
|
|
|
.storeAddress(params.nextAdminAddress)
|
|
|
|
.storeRef(params.content)
|
|
|
|
.storeRef(params.wallet_code)
|
|
|
|
.endCell();
|
|
|
|
}
|
|
|
|
|
|
|
|
function bufferToChunks(buff: Buffer, chunkSize: number) {
|
|
|
|
let chunks: Buffer[] = []
|
|
|
|
while (buff.byteLength > 0) {
|
|
|
|
chunks.push(buff.slice(0, chunkSize))
|
|
|
|
buff = buff.slice(chunkSize)
|
|
|
|
}
|
|
|
|
return chunks
|
|
|
|
}
|
|
|
|
|
|
|
|
export function makeSnakeCell(data: Buffer) {
|
|
|
|
let chunks = bufferToChunks(data, 127)
|
|
|
|
let rootCell = new Cell()
|
|
|
|
let curCell = rootCell
|
|
|
|
|
|
|
|
for (let i = 0; i < chunks.length; i++) {
|
|
|
|
let chunk = chunks[i]
|
|
|
|
|
|
|
|
curCell.bits.writeBuffer(chunk)
|
|
|
|
|
|
|
|
if (chunks[i + 1]) {
|
|
|
|
let nextCell = new Cell()
|
|
|
|
curCell.refs.push(nextCell)
|
|
|
|
curCell = nextCell
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return rootCell
|
|
|
|
}
|
|
|
|
|
|
|
|
export function getMinterAddress(params: { adminAddress: Address; supply: number, nextAdminAddress?: Address, content: Cell, wallet_code: Cell }, initCodeCell: Cell): Address {
|
|
|
|
return contractAddress({workchain: 0, initialData: minterData(params), initialCode: initCodeCell});
|
|
|
|
}
|
|
|
|
|
|
|
|
const OFF_CHAIN_CONTENT_PREFIX = 0x01
|
|
|
|
|
|
|
|
export function encodeOffChainContent(content: string) {
|
|
|
|
let data = Buffer.from(content)
|
|
|
|
let offChainPrefix = Buffer.from([OFF_CHAIN_CONTENT_PREFIX])
|
|
|
|
data = Buffer.concat([offChainPrefix, data])
|
|
|
|
return makeSnakeCell(data)
|
|
|
|
}
|
|
|
|
|
|
|
|
// storage#_ balance:(VarUInteger 16) owner_address:MsgAddressInt jetton_master_address:MsgAddressInt jetton_wallet_code:^Cell = Storage;
|
|
|
|
export function walletData(params: { balance: number, ownerAddress: Address, jettonMasterAddress: Address, jettonWalletCode: Cell }): Cell {
|
|
|
|
return beginCell()
|
|
|
|
.storeUint(params.balance, 15)
|
|
|
|
.storeAddress(params.ownerAddress)
|
|
|
|
.storeAddress(params.jettonMasterAddress)
|
|
|
|
.storeRef(params.jettonWalletCode)
|
|
|
|
.endCell();
|
|
|
|
}
|
|
|
|
|
|
|
|
export function getJettonAddress(ownerAddress: Address, jettonMasterAddress: Address, jettonWalletCode: Cell): Address {
|
|
|
|
return contractAddress({
|
|
|
|
workchain: 0,
|
|
|
|
initialData: walletData({balance: 0, ownerAddress, jettonMasterAddress, jettonWalletCode}),
|
|
|
|
initialCode: jettonWalletCode
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
export function transferMsg(amount: number, recipient: Address) {
|
|
|
|
return beginCell()
|
|
|
|
.storeUint(0xf8a7ea5, 32)
|
|
|
|
.storeUint(0, 64)
|
|
|
|
.storeCoins(amount)
|
|
|
|
.storeAddress(recipient)
|
|
|
|
.storeAddress(recipient)
|
|
|
|
.storeBit(false)
|
|
|
|
.storeCoins(0)
|
|
|
|
.storeBit(false)
|
|
|
|
.endCell();
|
|
|
|
}
|
|
|
|
|
|
|
|
export function TON(): number {
|
|
|
|
return 1000000000;
|
|
|
|
}
|
|
|
|
|
|
|
|
// message encoders for all ops (see contracts/imports/constants.fc for consts)
|
|
|
|
|
|
|
|
export function depositMsg(amount: number): Cell {
|
|
|
|
return beginCell().storeUint(0x77a33521, 32)
|
|
|
|
.storeUint(0, 64).storeCoins(amount).endCell();
|
|
|
|
}
|
|
|
|
|
|
|
|
export function withdrawMsg(amount: BN | number): Cell {
|
|
|
|
return beginCell().storeUint(0x47d1895f, 32).storeUint(0, 64).storeCoins(amount).endCell();
|
|
|
|
}
|
|
|
|
|
|
|
|
export async function getWallet(isTestnet: boolean = true) {
|
|
|
|
const client = new TonClient({
|
|
|
|
endpoint: `https://${isTestnet ? "testnet." : ""}toncenter.com/api/v2/jsonRPC`,
|
|
|
|
apiKey: isTestnet ? 'bed2b4589201ff3c575be653593f912a337c08eed416b60b02345763b9ee9c36' : 'a1e8a1055a387515158589dc7e9bad3035e7db2b9f9ea5cdad6b727f71e328db'
|
|
|
|
});
|
|
|
|
let deployerMnemonic = process.env.DEPLOYER_MNEMONIC;
|
|
|
|
if (!deployerMnemonic) throw new Error("DEPLOYER_MNEMONIC env var is not set");
|
|
|
|
|
|
|
|
// open the wallet and make sure it has enough TON
|
|
|
|
const walletKey = await mnemonicToWalletKey(deployerMnemonic.split(" "));
|
|
|
|
let workchain = 0;
|
|
|
|
return [WalletContract.create(client, WalletV3R2Source.create({
|
|
|
|
publicKey: walletKey.publicKey,
|
|
|
|
workchain
|
|
|
|
})), walletKey];
|
|
|
|
}
|