@pizzaton/ton 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRACTS.md +239 -0
- package/README.md +481 -2
- package/dist/airdrop/index.d.mts +18 -0
- package/dist/airdrop/index.mjs +86 -0
- package/dist/connect/errors.d.mts +4 -0
- package/dist/connect/errors.mjs +21 -0
- package/dist/connect/index.d.mts +23 -0
- package/dist/connect/index.mjs +34 -0
- package/dist/contracts/catalog/index.d.mts +361 -0
- package/dist/contracts/catalog/index.mjs +403 -0
- package/dist/contracts/client.d.mts +18 -0
- package/dist/contracts/client.mjs +31 -0
- package/dist/contracts/codecs.d.mts +14 -0
- package/dist/contracts/codecs.mjs +61 -0
- package/dist/contracts/hipo.d.mts +138 -0
- package/dist/contracts/hipo.mjs +198 -0
- package/dist/contracts/index.d.mts +23 -0
- package/dist/contracts/index.mjs +20 -0
- package/dist/contracts/metadata.d.mts +38 -0
- package/dist/contracts/metadata.mjs +50 -0
- package/dist/contracts/module-client.d.mts +20 -0
- package/dist/contracts/module-client.mjs +34 -0
- package/dist/contracts/module.d.mts +8 -0
- package/dist/contracts/module.mjs +11 -0
- package/dist/contracts/wrappers/base.d.mts +18 -0
- package/dist/contracts/wrappers/base.mjs +31 -0
- package/dist/contracts/wrappers/index.d.mts +12 -0
- package/dist/contracts/wrappers/index.mjs +12 -0
- package/dist/contracts/wrappers/jvault-protocols.d.mts +206 -0
- package/dist/contracts/wrappers/jvault-protocols.mjs +432 -0
- package/dist/contracts/wrappers/jvault-support.d.mts +135 -0
- package/dist/contracts/wrappers/jvault-support.mjs +269 -0
- package/dist/contracts/wrappers/jvault.d.mts +123 -0
- package/dist/contracts/wrappers/jvault.mjs +258 -0
- package/dist/contracts/wrappers/memeland.d.mts +253 -0
- package/dist/contracts/wrappers/memeland.mjs +396 -0
- package/dist/contracts/wrappers/multix.d.mts +92 -0
- package/dist/contracts/wrappers/multix.mjs +156 -0
- package/dist/contracts/wrappers/pizzabox.d.mts +66 -0
- package/dist/contracts/wrappers/pizzabox.mjs +105 -0
- package/dist/contracts/wrappers/ton-raffles.d.mts +215 -0
- package/dist/contracts/wrappers/ton-raffles.mjs +398 -0
- package/dist/contracts/wrappers/tonresistor.d.mts +189 -0
- package/dist/contracts/wrappers/tonresistor.mjs +276 -0
- package/dist/core/address.d.mts +25 -0
- package/dist/core/address.mjs +45 -0
- package/dist/core/amount.d.mts +8 -0
- package/dist/core/amount.mjs +34 -0
- package/dist/core/bytes.d.mts +5 -0
- package/dist/core/bytes.mjs +18 -0
- package/dist/core/constants.d.mts +14 -0
- package/dist/core/constants.mjs +15 -0
- package/dist/core/errors.d.mts +9 -0
- package/dist/core/errors.mjs +16 -0
- package/dist/core/http.mjs +39 -0
- package/dist/core/index.d.mts +8 -0
- package/dist/core/index.mjs +8 -0
- package/dist/core/metadata.d.mts +12 -0
- package/dist/core/metadata.mjs +35 -0
- package/dist/core/network.d.mts +24 -0
- package/dist/core/network.mjs +41 -0
- package/dist/emulator/index.d.mts +20 -0
- package/dist/emulator/index.mjs +24 -0
- package/dist/index.d.mts +21 -0
- package/dist/index.mjs +19 -0
- package/dist/indexer/index.d.mts +90 -0
- package/dist/indexer/index.mjs +279 -0
- package/dist/jetton/details.d.mts +27 -0
- package/dist/jetton/details.mjs +116 -0
- package/dist/jetton/index.d.mts +54 -0
- package/dist/jetton/index.mjs +92 -0
- package/dist/jetton/versions.d.mts +12 -0
- package/dist/jetton/versions.mjs +50 -0
- package/dist/nft/collection.d.mts +57 -0
- package/dist/nft/collection.mjs +148 -0
- package/dist/nft/content.d.mts +34 -0
- package/dist/nft/content.mjs +142 -0
- package/dist/nft/index.d.mts +35 -0
- package/dist/nft/index.mjs +51 -0
- package/dist/nft/versions.d.mts +11 -0
- package/dist/nft/versions.mjs +29 -0
- package/dist/provider/index.d.mts +32 -0
- package/dist/provider/index.mjs +1 -0
- package/dist/react/index.d.mts +13 -0
- package/dist/react/index.mjs +48 -0
- package/dist/server/index.d.mts +11 -0
- package/dist/server/index.mjs +55 -0
- package/dist/simulation/index.d.mts +112 -0
- package/dist/simulation/index.mjs +310 -0
- package/dist/transactions/index.d.mts +33 -0
- package/dist/transactions/index.mjs +51 -0
- package/dist/vesting/index.d.mts +12 -0
- package/dist/vesting/index.mjs +25 -0
- package/dist/wallet/index.d.mts +23 -0
- package/dist/wallet/index.mjs +71 -0
- package/package.json +169 -5
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { invariant } from "../core/errors.mjs";
|
|
2
|
+
import { MAX_TON_COINS, assertTonAmount, parseUnits } from "../core/amount.mjs";
|
|
3
|
+
import { JETTON_IMPLEMENTATION_PROFILES, getJettonImplementationProfile } from "./versions.mjs";
|
|
4
|
+
import { SendMode, TupleBuilder, beginCell } from "@ton/core";
|
|
5
|
+
import { JettonMaster, JettonMaster as JettonMasterContract, JettonWallet, JettonWallet as JettonWallet$1 } from "@ton/ton";
|
|
6
|
+
//#region src/jetton/index.ts
|
|
7
|
+
const JETTON_OPCODES = {
|
|
8
|
+
transfer: 260734629,
|
|
9
|
+
burn: 1499400124,
|
|
10
|
+
excesses: 3576854235,
|
|
11
|
+
internalTransfer: 395134233,
|
|
12
|
+
transferNotification: 1935855772
|
|
13
|
+
};
|
|
14
|
+
var JettonWalletContract = class JettonWalletContract {
|
|
15
|
+
address;
|
|
16
|
+
official;
|
|
17
|
+
constructor(address) {
|
|
18
|
+
this.official = JettonWallet$1.create(address);
|
|
19
|
+
this.address = this.official.address;
|
|
20
|
+
}
|
|
21
|
+
static create(address) {
|
|
22
|
+
return new JettonWalletContract(address);
|
|
23
|
+
}
|
|
24
|
+
async getBalance(provider) {
|
|
25
|
+
return this.official.getBalance(provider);
|
|
26
|
+
}
|
|
27
|
+
async getWalletData(provider) {
|
|
28
|
+
const { stack } = await provider.get("get_wallet_data", []);
|
|
29
|
+
return {
|
|
30
|
+
balance: stack.readBigNumber(),
|
|
31
|
+
owner: stack.readAddress(),
|
|
32
|
+
master: stack.readAddress(),
|
|
33
|
+
walletCode: stack.readCell()
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
async sendTransfer(provider, via, input, value) {
|
|
37
|
+
assertTonAmount(value, "Jetton transfer value");
|
|
38
|
+
await provider.internal(via, {
|
|
39
|
+
value,
|
|
40
|
+
body: buildJettonTransferBody(input),
|
|
41
|
+
sendMode: SendMode.PAY_GAS_SEPARATELY
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
async sendBurn(provider, via, input, value) {
|
|
45
|
+
assertTonAmount(value, "Jetton burn value");
|
|
46
|
+
await provider.internal(via, {
|
|
47
|
+
value,
|
|
48
|
+
body: buildJettonBurnBody(input),
|
|
49
|
+
sendMode: SendMode.PAY_GAS_SEPARATELY
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
function buildJettonTransferBody(input) {
|
|
54
|
+
assertAmount(input.amount);
|
|
55
|
+
assertQueryId(input.queryId);
|
|
56
|
+
const forwardAmount = input.forwardAmount ?? 0n;
|
|
57
|
+
invariant(forwardAmount >= 0n && forwardAmount <= MAX_TON_COINS, "INVALID_AMOUNT", "Forward amount is outside the TON coin range");
|
|
58
|
+
const builder = beginCell().storeUint(JETTON_OPCODES.transfer, 32).storeUint(input.queryId ?? 0n, 64).storeCoins(input.amount).storeAddress(input.destination).storeAddress(input.responseDestination).storeMaybeRef(input.customPayload).storeCoins(forwardAmount);
|
|
59
|
+
if (input.forwardPayload) builder.storeBit(1).storeRef(input.forwardPayload);
|
|
60
|
+
else builder.storeBit(0);
|
|
61
|
+
return builder.endCell();
|
|
62
|
+
}
|
|
63
|
+
function buildJettonBurnBody(input) {
|
|
64
|
+
assertAmount(input.amount);
|
|
65
|
+
assertQueryId(input.queryId);
|
|
66
|
+
return beginCell().storeUint(JETTON_OPCODES.burn, 32).storeUint(input.queryId ?? 0n, 64).storeCoins(input.amount).storeAddress(input.responseDestination).storeMaybeRef(input.customPayload).endCell();
|
|
67
|
+
}
|
|
68
|
+
function buildJettonExcessesBody(queryId = 0n) {
|
|
69
|
+
assertQueryId(queryId);
|
|
70
|
+
return beginCell().storeUint(JETTON_OPCODES.excesses, 32).storeUint(queryId, 64).endCell();
|
|
71
|
+
}
|
|
72
|
+
function buildJettonGetWalletAddressArgs(owner) {
|
|
73
|
+
const tuple = new TupleBuilder();
|
|
74
|
+
tuple.writeAddress(owner);
|
|
75
|
+
return tuple;
|
|
76
|
+
}
|
|
77
|
+
async function resolveJettonWalletAddress(provider, master, owner) {
|
|
78
|
+
const result = await provider.runGetMethod(master, "get_wallet_address", buildJettonGetWalletAddressArgs(owner).build());
|
|
79
|
+
invariant(result.exitCode === void 0 || result.exitCode === 0, "PROVIDER_ERROR", `Jetton wallet address getter failed with exit code ${result.exitCode}`, { exitCode: result.exitCode });
|
|
80
|
+
return result.stack.readAddress();
|
|
81
|
+
}
|
|
82
|
+
function parseJettonAmount(value, decimals) {
|
|
83
|
+
return parseUnits(value, decimals);
|
|
84
|
+
}
|
|
85
|
+
function assertAmount(value) {
|
|
86
|
+
invariant(value >= 0n && value <= MAX_TON_COINS, "INVALID_AMOUNT", "Jetton amount is out of range");
|
|
87
|
+
}
|
|
88
|
+
function assertQueryId(value) {
|
|
89
|
+
if (value !== void 0) invariant(value >= 0n && value < 2n ** 64n, "INVALID_TRANSACTION", "Query id is out of range");
|
|
90
|
+
}
|
|
91
|
+
//#endregion
|
|
92
|
+
export { JETTON_IMPLEMENTATION_PROFILES, JETTON_OPCODES, JettonMaster, JettonMasterContract, JettonWallet, JettonWalletContract, buildJettonBurnBody, buildJettonExcessesBody, buildJettonGetWalletAddressArgs, buildJettonTransferBody, getJettonImplementationProfile, parseJettonAmount, resolveJettonWalletAddress };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/jetton/versions.d.ts
|
|
2
|
+
export type JettonImplementationVersion = "jetton-1.0" | "discoverable" | "stablecoin" | "notcoin" | "mintless" | "jetton-2.0";
|
|
3
|
+
export interface JettonImplementationProfile {
|
|
4
|
+
readonly version: JettonImplementationVersion;
|
|
5
|
+
readonly supportsWalletDiscovery: boolean;
|
|
6
|
+
readonly supportsBurn: boolean;
|
|
7
|
+
readonly supportsCustomTransferPayload: boolean;
|
|
8
|
+
readonly optimizedWalletSharding: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare const JETTON_IMPLEMENTATION_PROFILES: Readonly<Record<JettonImplementationVersion, JettonImplementationProfile>>;
|
|
11
|
+
export declare function getJettonImplementationProfile(version: JettonImplementationVersion): JettonImplementationProfile;
|
|
12
|
+
//#endregion
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
//#region src/jetton/versions.ts
|
|
2
|
+
const JETTON_IMPLEMENTATION_PROFILES = Object.freeze({
|
|
3
|
+
"jetton-1.0": {
|
|
4
|
+
version: "jetton-1.0",
|
|
5
|
+
supportsWalletDiscovery: false,
|
|
6
|
+
supportsBurn: true,
|
|
7
|
+
supportsCustomTransferPayload: true,
|
|
8
|
+
optimizedWalletSharding: false
|
|
9
|
+
},
|
|
10
|
+
discoverable: {
|
|
11
|
+
version: "discoverable",
|
|
12
|
+
supportsWalletDiscovery: true,
|
|
13
|
+
supportsBurn: true,
|
|
14
|
+
supportsCustomTransferPayload: true,
|
|
15
|
+
optimizedWalletSharding: false
|
|
16
|
+
},
|
|
17
|
+
stablecoin: {
|
|
18
|
+
version: "stablecoin",
|
|
19
|
+
supportsWalletDiscovery: true,
|
|
20
|
+
supportsBurn: false,
|
|
21
|
+
supportsCustomTransferPayload: true,
|
|
22
|
+
optimizedWalletSharding: false
|
|
23
|
+
},
|
|
24
|
+
notcoin: {
|
|
25
|
+
version: "notcoin",
|
|
26
|
+
supportsWalletDiscovery: true,
|
|
27
|
+
supportsBurn: true,
|
|
28
|
+
supportsCustomTransferPayload: true,
|
|
29
|
+
optimizedWalletSharding: false
|
|
30
|
+
},
|
|
31
|
+
mintless: {
|
|
32
|
+
version: "mintless",
|
|
33
|
+
supportsWalletDiscovery: true,
|
|
34
|
+
supportsBurn: true,
|
|
35
|
+
supportsCustomTransferPayload: true,
|
|
36
|
+
optimizedWalletSharding: false
|
|
37
|
+
},
|
|
38
|
+
"jetton-2.0": {
|
|
39
|
+
version: "jetton-2.0",
|
|
40
|
+
supportsWalletDiscovery: true,
|
|
41
|
+
supportsBurn: true,
|
|
42
|
+
supportsCustomTransferPayload: true,
|
|
43
|
+
optimizedWalletSharding: true
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
function getJettonImplementationProfile(version) {
|
|
47
|
+
return JETTON_IMPLEMENTATION_PROFILES[version];
|
|
48
|
+
}
|
|
49
|
+
//#endregion
|
|
50
|
+
export { JETTON_IMPLEMENTATION_PROFILES, getJettonImplementationProfile };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { NftContent, RoyaltyParameters } from "./content.mjs";
|
|
2
|
+
import { Address, Cell, Contract, ContractProvider, Sender } from "@ton/core";
|
|
3
|
+
//#region src/nft/collection.d.ts
|
|
4
|
+
export declare const NFT_COLLECTION_OPCODES: {
|
|
5
|
+
readonly deployItem: 1;
|
|
6
|
+
readonly batchDeployItem: 2;
|
|
7
|
+
readonly changeOwner: 3;
|
|
8
|
+
readonly getRoyaltyParams: 1765620048;
|
|
9
|
+
};
|
|
10
|
+
export interface NftCollectionConfig {
|
|
11
|
+
readonly admin: Address;
|
|
12
|
+
readonly content: NftContent | Cell;
|
|
13
|
+
readonly commonContent: string;
|
|
14
|
+
readonly itemCode: Cell;
|
|
15
|
+
readonly royalty: RoyaltyParameters;
|
|
16
|
+
}
|
|
17
|
+
export interface NewNftItem {
|
|
18
|
+
readonly owner: Address;
|
|
19
|
+
readonly content: NftContent | Cell;
|
|
20
|
+
}
|
|
21
|
+
export interface NftCollectionData {
|
|
22
|
+
readonly nextItemIndex: bigint;
|
|
23
|
+
readonly collectionContent: Cell;
|
|
24
|
+
readonly owner: Address;
|
|
25
|
+
}
|
|
26
|
+
export declare function collectionConfigToCell(config: NftCollectionConfig): Cell;
|
|
27
|
+
export declare function buildNftDeployItemBody(item: NewNftItem, index: bigint | number, forwardAmount: bigint, queryId?: bigint | number): Cell;
|
|
28
|
+
export declare function buildNftChangeOwnerBody(newOwner: Address, queryId?: bigint | number): Cell;
|
|
29
|
+
export declare function buildNftBatchDeployBody(items: readonly {
|
|
30
|
+
readonly index: bigint | number;
|
|
31
|
+
readonly item: NewNftItem;
|
|
32
|
+
readonly forwardAmount: bigint;
|
|
33
|
+
}[], queryId?: bigint | number): Cell;
|
|
34
|
+
export declare function buildNftRoyaltyParamsBody(queryId?: bigint | number): Cell;
|
|
35
|
+
export declare class NftCollectionContract implements Contract {
|
|
36
|
+
readonly init?: {
|
|
37
|
+
readonly code: Cell;
|
|
38
|
+
readonly data: Cell;
|
|
39
|
+
} | undefined;
|
|
40
|
+
readonly address: Address;
|
|
41
|
+
private constructor();
|
|
42
|
+
static createFromAddress(address: Address): NftCollectionContract;
|
|
43
|
+
static createFromConfig(config: NftCollectionConfig, code: Cell, workchain?: number): NftCollectionContract;
|
|
44
|
+
sendDeploy(provider: ContractProvider, via: Sender, value: bigint): Promise<void>;
|
|
45
|
+
sendDeployItem(provider: ContractProvider, via: Sender, item: NewNftItem, index: bigint | number, forwardAmount?: bigint, value?: bigint, queryId?: bigint | number): Promise<void>;
|
|
46
|
+
sendChangeOwner(provider: ContractProvider, via: Sender, newOwner: Address, value?: bigint, queryId?: bigint | number): Promise<void>;
|
|
47
|
+
sendDeployBatch(provider: ContractProvider, via: Sender, items: readonly {
|
|
48
|
+
readonly item: NewNftItem;
|
|
49
|
+
readonly index: bigint | number;
|
|
50
|
+
readonly forwardAmount: bigint;
|
|
51
|
+
}[], value: bigint, queryId?: bigint | number): Promise<void>;
|
|
52
|
+
sendGetRoyaltyParams(provider: ContractProvider, via: Sender, value?: bigint, queryId?: bigint | number): Promise<void>;
|
|
53
|
+
getNftAddressByIndex(provider: ContractProvider, index: bigint | number): Promise<Address>;
|
|
54
|
+
getCollectionData(provider: ContractProvider): Promise<NftCollectionData>;
|
|
55
|
+
getNftContent(provider: ContractProvider, index: bigint | number, content: Cell): Promise<Cell>;
|
|
56
|
+
}
|
|
57
|
+
//#endregion
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { invariant } from "../core/errors.mjs";
|
|
2
|
+
import { MAX_TON_COINS, assertTonAmount } from "../core/amount.mjs";
|
|
3
|
+
import { nftContentToCell, royaltyParamsToCell } from "./content.mjs";
|
|
4
|
+
import { Cell, Dictionary, SendMode, beginCell, contractAddress, toNano } from "@ton/core";
|
|
5
|
+
//#region src/nft/collection.ts
|
|
6
|
+
const NFT_COLLECTION_OPCODES = {
|
|
7
|
+
deployItem: 1,
|
|
8
|
+
batchDeployItem: 2,
|
|
9
|
+
changeOwner: 3,
|
|
10
|
+
getRoyaltyParams: 1765620048
|
|
11
|
+
};
|
|
12
|
+
function collectionConfigToCell(config) {
|
|
13
|
+
return beginCell().storeAddress(config.admin).storeUint(0, 64).storeRef(beginCell().storeRef(config.content instanceof Cell ? config.content : nftContentToCell(config.content)).storeRef(beginCell().storeStringTail(config.commonContent).endCell()).endCell()).storeRef(config.itemCode).storeRef(royaltyParamsToCell(config.royalty)).endCell();
|
|
14
|
+
}
|
|
15
|
+
function assertQueryId(queryId) {
|
|
16
|
+
invariant(typeof queryId === "bigint" || Number.isSafeInteger(queryId), "INVALID_TRANSACTION", "Query id must be a safe integer");
|
|
17
|
+
const value = BigInt(queryId);
|
|
18
|
+
invariant(value >= 0n && value < 2n ** 64n, "INVALID_TRANSACTION", "Query id is out of range");
|
|
19
|
+
return value;
|
|
20
|
+
}
|
|
21
|
+
function assertIndex(index) {
|
|
22
|
+
invariant(typeof index === "bigint" || Number.isSafeInteger(index), "INVALID_TRANSACTION", "NFT index must be a safe integer");
|
|
23
|
+
const value = BigInt(index);
|
|
24
|
+
invariant(value >= 0n && value < 2n ** 64n, "INVALID_TRANSACTION", "NFT index is out of range");
|
|
25
|
+
return value;
|
|
26
|
+
}
|
|
27
|
+
function buildNftDeployItemBody(item, index, forwardAmount, queryId = 0n) {
|
|
28
|
+
invariant(forwardAmount >= 0n && forwardAmount <= MAX_TON_COINS, "INVALID_AMOUNT", "Forward amount is outside the TON coin range");
|
|
29
|
+
return beginCell().storeUint(NFT_COLLECTION_OPCODES.deployItem, 32).storeUint(assertQueryId(queryId), 64).storeUint(assertIndex(index), 64).storeCoins(forwardAmount).storeRef(beginCell().storeAddress(item.owner).storeRef(item.content instanceof Cell ? item.content : nftContentToCell(item.content)).endCell()).endCell();
|
|
30
|
+
}
|
|
31
|
+
function buildNftChangeOwnerBody(newOwner, queryId = 0n) {
|
|
32
|
+
return beginCell().storeUint(NFT_COLLECTION_OPCODES.changeOwner, 32).storeUint(assertQueryId(queryId), 64).storeAddress(newOwner).endCell();
|
|
33
|
+
}
|
|
34
|
+
function batchDeployValue() {
|
|
35
|
+
return {
|
|
36
|
+
parse(slice) {
|
|
37
|
+
const content = slice.loadRef().beginParse();
|
|
38
|
+
return {
|
|
39
|
+
forwardAmount: slice.loadCoins(),
|
|
40
|
+
owner: content.loadAddress(),
|
|
41
|
+
content: content.loadRef()
|
|
42
|
+
};
|
|
43
|
+
},
|
|
44
|
+
serialize(value, builder) {
|
|
45
|
+
invariant(value.forwardAmount >= 0n && value.forwardAmount <= MAX_TON_COINS, "INVALID_AMOUNT", "Forward amount is outside the TON coin range");
|
|
46
|
+
builder.storeCoins(value.forwardAmount).storeRef(beginCell().storeAddress(value.owner).storeRef(value.content instanceof Cell ? value.content : nftContentToCell(value.content)).endCell());
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function buildNftBatchDeployBody(items, queryId = 0n) {
|
|
51
|
+
const dictionary = Dictionary.empty(Dictionary.Keys.BigUint(64), batchDeployValue());
|
|
52
|
+
for (const entry of items) {
|
|
53
|
+
invariant(entry.forwardAmount >= 0n && entry.forwardAmount <= MAX_TON_COINS, "INVALID_AMOUNT", "Forward amount is outside the TON coin range");
|
|
54
|
+
dictionary.set(assertIndex(entry.index), {
|
|
55
|
+
...entry.item,
|
|
56
|
+
forwardAmount: entry.forwardAmount
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
return beginCell().storeUint(NFT_COLLECTION_OPCODES.batchDeployItem, 32).storeUint(assertQueryId(queryId), 64).storeDict(dictionary).endCell();
|
|
60
|
+
}
|
|
61
|
+
function buildNftRoyaltyParamsBody(queryId = 0n) {
|
|
62
|
+
return beginCell().storeUint(NFT_COLLECTION_OPCODES.getRoyaltyParams, 32).storeUint(assertQueryId(queryId), 64).endCell();
|
|
63
|
+
}
|
|
64
|
+
var NftCollectionContract = class NftCollectionContract {
|
|
65
|
+
init;
|
|
66
|
+
address;
|
|
67
|
+
constructor(address, init) {
|
|
68
|
+
this.init = init;
|
|
69
|
+
this.address = address;
|
|
70
|
+
}
|
|
71
|
+
static createFromAddress(address) {
|
|
72
|
+
return new NftCollectionContract(address);
|
|
73
|
+
}
|
|
74
|
+
static createFromConfig(config, code, workchain = 0) {
|
|
75
|
+
const init = {
|
|
76
|
+
code,
|
|
77
|
+
data: collectionConfigToCell(config)
|
|
78
|
+
};
|
|
79
|
+
return new NftCollectionContract(contractAddress(workchain, init), init);
|
|
80
|
+
}
|
|
81
|
+
async sendDeploy(provider, via, value) {
|
|
82
|
+
assertTonAmount(value, "NFT deployment value");
|
|
83
|
+
await provider.internal(via, {
|
|
84
|
+
value,
|
|
85
|
+
sendMode: SendMode.PAY_GAS_SEPARATELY,
|
|
86
|
+
body: beginCell().endCell()
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
async sendDeployItem(provider, via, item, index, forwardAmount = toNano("0.06"), value = toNano("0.07"), queryId = 0n) {
|
|
90
|
+
assertTonAmount(value, "NFT item deployment value");
|
|
91
|
+
await provider.internal(via, {
|
|
92
|
+
value,
|
|
93
|
+
body: buildNftDeployItemBody(item, index, forwardAmount, queryId),
|
|
94
|
+
sendMode: SendMode.PAY_GAS_SEPARATELY
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
async sendChangeOwner(provider, via, newOwner, value = toNano("0.05"), queryId = 0n) {
|
|
98
|
+
assertTonAmount(value, "NFT owner change value");
|
|
99
|
+
await provider.internal(via, {
|
|
100
|
+
value,
|
|
101
|
+
body: buildNftChangeOwnerBody(newOwner, queryId),
|
|
102
|
+
sendMode: SendMode.PAY_GAS_SEPARATELY
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
async sendDeployBatch(provider, via, items, value, queryId = 0n) {
|
|
106
|
+
assertTonAmount(value, "NFT batch deployment value");
|
|
107
|
+
await provider.internal(via, {
|
|
108
|
+
value,
|
|
109
|
+
body: buildNftBatchDeployBody(items, queryId),
|
|
110
|
+
sendMode: SendMode.PAY_GAS_SEPARATELY
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
async sendGetRoyaltyParams(provider, via, value = toNano("0.05"), queryId = 0n) {
|
|
114
|
+
assertTonAmount(value, "NFT royalty request value");
|
|
115
|
+
await provider.internal(via, {
|
|
116
|
+
value,
|
|
117
|
+
body: buildNftRoyaltyParamsBody(queryId),
|
|
118
|
+
sendMode: SendMode.PAY_GAS_SEPARATELY
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
async getNftAddressByIndex(provider, index) {
|
|
122
|
+
const { stack } = await provider.get("get_nft_address_by_index", [{
|
|
123
|
+
type: "int",
|
|
124
|
+
value: assertIndex(index)
|
|
125
|
+
}]);
|
|
126
|
+
return stack.readAddress();
|
|
127
|
+
}
|
|
128
|
+
async getCollectionData(provider) {
|
|
129
|
+
const { stack } = await provider.get("get_collection_data", []);
|
|
130
|
+
return {
|
|
131
|
+
nextItemIndex: stack.readBigNumber(),
|
|
132
|
+
collectionContent: stack.readCell(),
|
|
133
|
+
owner: stack.readAddress()
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
async getNftContent(provider, index, content) {
|
|
137
|
+
const { stack } = await provider.get("get_nft_content", [{
|
|
138
|
+
type: "int",
|
|
139
|
+
value: assertIndex(index)
|
|
140
|
+
}, {
|
|
141
|
+
type: "cell",
|
|
142
|
+
cell: content
|
|
143
|
+
}]);
|
|
144
|
+
return stack.readCell();
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
//#endregion
|
|
148
|
+
export { NFT_COLLECTION_OPCODES, NftCollectionContract, buildNftBatchDeployBody, buildNftChangeOwnerBody, buildNftDeployItemBody, buildNftRoyaltyParamsBody, collectionConfigToCell };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Builder, Cell, Slice } from "@ton/core";
|
|
2
|
+
//#region src/nft/content.d.ts
|
|
3
|
+
export declare const NFT_ONCHAIN_CONTENT_KEYS: readonly ["uri", "name", "description", "image", "image_data", "symbol", "decimals", "amount_style", "render_type", "currency", "game"];
|
|
4
|
+
export type NftOnchainContentKey = (typeof NFT_ONCHAIN_CONTENT_KEYS)[number];
|
|
5
|
+
export interface NftContentOffchain {
|
|
6
|
+
readonly type: "offchain";
|
|
7
|
+
readonly uri: string;
|
|
8
|
+
}
|
|
9
|
+
export interface NftContentOnchain {
|
|
10
|
+
readonly type: "onchain";
|
|
11
|
+
readonly data: Partial<Record<NftOnchainContentKey, string>>;
|
|
12
|
+
}
|
|
13
|
+
export type NftContent = NftContentOffchain | NftContentOnchain;
|
|
14
|
+
export interface RoyaltyParameters {
|
|
15
|
+
readonly address: import("@ton/core").Address;
|
|
16
|
+
readonly royaltyFactor: bigint | number;
|
|
17
|
+
readonly royaltyBase: bigint | number;
|
|
18
|
+
}
|
|
19
|
+
export declare function nftContentToCell(content: NftContent): Cell;
|
|
20
|
+
/**
|
|
21
|
+
* Build TEP-64 on-chain metadata for protocol-specific keys.
|
|
22
|
+
*
|
|
23
|
+
* Standard NFT metadata exposes a curated key union above. Some audited
|
|
24
|
+
* protocol contracts add namespaced keys of their own; this helper keeps the
|
|
25
|
+
* same canonical SHA-256 key/value encoding without weakening the standard
|
|
26
|
+
* parser's typed surface.
|
|
27
|
+
*/
|
|
28
|
+
export declare function buildOnchainMetadata(data: Readonly<Record<string, string>>): Cell;
|
|
29
|
+
export declare function nftContentFromCell(cell: Cell): NftContent;
|
|
30
|
+
export declare function royaltyParamsToCell(royalty: RoyaltyParameters): Cell;
|
|
31
|
+
export declare function assertCell(value: Cell | unknown, message: string): asserts value is Cell;
|
|
32
|
+
export declare function storeNftContent(builder: Builder, content: NftContent | Cell): Builder;
|
|
33
|
+
export declare function parseNftContentSlice(slice: Slice): NftContent;
|
|
34
|
+
//#endregion
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { invariant } from "../core/errors.mjs";
|
|
2
|
+
import { Cell, Dictionary, beginCell } from "@ton/core";
|
|
3
|
+
import { sha256_sync } from "@ton/crypto";
|
|
4
|
+
//#region src/nft/content.ts
|
|
5
|
+
const NFT_ONCHAIN_CONTENT_KEYS = [
|
|
6
|
+
"uri",
|
|
7
|
+
"name",
|
|
8
|
+
"description",
|
|
9
|
+
"image",
|
|
10
|
+
"image_data",
|
|
11
|
+
"symbol",
|
|
12
|
+
"decimals",
|
|
13
|
+
"amount_style",
|
|
14
|
+
"render_type",
|
|
15
|
+
"currency",
|
|
16
|
+
"game"
|
|
17
|
+
];
|
|
18
|
+
function onchainStringValue() {
|
|
19
|
+
return {
|
|
20
|
+
serialize(value, builder) {
|
|
21
|
+
const bytes = Buffer.from(value, "utf8");
|
|
22
|
+
if (bytes.length <= 126) {
|
|
23
|
+
builder.storeRef(beginCell().storeUint(0, 8).storeBuffer(bytes));
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const chunkDictionary = Dictionary.empty(Dictionary.Keys.Uint(32), Dictionary.Values.Cell());
|
|
27
|
+
for (const [index, chunk] of splitBytes(bytes, 127).entries()) chunkDictionary.set(index, snakeBytesCell(chunk));
|
|
28
|
+
builder.storeRef(beginCell().storeUint(1, 8).storeDict(chunkDictionary).endCell());
|
|
29
|
+
},
|
|
30
|
+
parse(slice) {
|
|
31
|
+
const value = slice.loadRef().beginParse();
|
|
32
|
+
const tag = value.loadUint(8);
|
|
33
|
+
if (tag === 0) return loadSnakeString(value);
|
|
34
|
+
if (tag === 1) {
|
|
35
|
+
const chunks = Dictionary.load(Dictionary.Keys.Uint(32), Dictionary.Values.Cell(), value);
|
|
36
|
+
return Buffer.concat(chunks.values().map((chunk) => loadSnakeBytesCell(chunk))).toString("utf8");
|
|
37
|
+
}
|
|
38
|
+
throw new Error(`Unsupported on-chain metadata string prefix: ${tag}`);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function splitBytes(value, chunkSize) {
|
|
43
|
+
const chunks = [];
|
|
44
|
+
for (let offset = 0; offset < value.length; offset += chunkSize) chunks.push(value.subarray(offset, offset + chunkSize));
|
|
45
|
+
return chunks;
|
|
46
|
+
}
|
|
47
|
+
function snakeBytesCell(value) {
|
|
48
|
+
const chunks = splitBytes(value, 127);
|
|
49
|
+
let next;
|
|
50
|
+
for (let index = chunks.length - 1; index >= 1; index -= 1) {
|
|
51
|
+
const chunk = chunks[index];
|
|
52
|
+
if (!chunk) continue;
|
|
53
|
+
const builder = beginCell().storeBuffer(Buffer.from(chunk));
|
|
54
|
+
if (next) builder.storeRef(next);
|
|
55
|
+
next = builder.endCell();
|
|
56
|
+
}
|
|
57
|
+
const builder = beginCell().storeBuffer(Buffer.from(chunks[0] ?? /* @__PURE__ */ new Uint8Array()));
|
|
58
|
+
if (next) builder.storeRef(next);
|
|
59
|
+
return builder.endCell();
|
|
60
|
+
}
|
|
61
|
+
function loadSnakeBytesCell(cell) {
|
|
62
|
+
return loadSnakeBytes(cell.beginParse());
|
|
63
|
+
}
|
|
64
|
+
function loadSnakeString(slice) {
|
|
65
|
+
return loadSnakeBytes(slice).toString("utf8");
|
|
66
|
+
}
|
|
67
|
+
function loadSnakeBytes(slice) {
|
|
68
|
+
const parts = [];
|
|
69
|
+
let current = slice;
|
|
70
|
+
let cellCount = 0;
|
|
71
|
+
while (current) {
|
|
72
|
+
cellCount += 1;
|
|
73
|
+
invariant(cellCount <= 1e4, "INVALID_METADATA", "Metadata snake exceeds the cell limit");
|
|
74
|
+
invariant(current.remainingBits % 8 === 0, "INVALID_METADATA", "Metadata snake contains a partial byte");
|
|
75
|
+
parts.push(current.loadBuffer(current.remainingBits / 8));
|
|
76
|
+
invariant(current.remainingRefs <= 1, "INVALID_METADATA", "Metadata snake contains multiple continuation cells");
|
|
77
|
+
current = current.remainingRefs > 0 ? current.loadRef().beginParse() : void 0;
|
|
78
|
+
}
|
|
79
|
+
return Buffer.concat(parts);
|
|
80
|
+
}
|
|
81
|
+
function nftContentToCell(content) {
|
|
82
|
+
if (content.type === "offchain") {
|
|
83
|
+
const bytes = Buffer.from(content.uri, "utf8");
|
|
84
|
+
const first = bytes.subarray(0, 126);
|
|
85
|
+
const builder = beginCell().storeUint(1, 8).storeBuffer(first);
|
|
86
|
+
if (bytes.length > first.length) builder.storeRef(snakeBytesCell(bytes.subarray(first.length)));
|
|
87
|
+
return builder.endCell();
|
|
88
|
+
}
|
|
89
|
+
const allowedKeys = new Set(NFT_ONCHAIN_CONTENT_KEYS);
|
|
90
|
+
const dictionary = Dictionary.empty(Dictionary.Keys.Buffer(32), onchainStringValue());
|
|
91
|
+
for (const [key, value] of Object.entries(content.data)) if (value !== void 0 && allowedKeys.has(key)) dictionary.set(sha256_sync(key), value);
|
|
92
|
+
return beginCell().storeUint(0, 8).storeDict(dictionary).endCell();
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Build TEP-64 on-chain metadata for protocol-specific keys.
|
|
96
|
+
*
|
|
97
|
+
* Standard NFT metadata exposes a curated key union above. Some audited
|
|
98
|
+
* protocol contracts add namespaced keys of their own; this helper keeps the
|
|
99
|
+
* same canonical SHA-256 key/value encoding without weakening the standard
|
|
100
|
+
* parser's typed surface.
|
|
101
|
+
*/
|
|
102
|
+
function buildOnchainMetadata(data) {
|
|
103
|
+
const dictionary = Dictionary.empty(Dictionary.Keys.Buffer(32), onchainStringValue());
|
|
104
|
+
for (const [key, value] of Object.entries(data)) dictionary.set(sha256_sync(key), value);
|
|
105
|
+
return beginCell().storeUint(0, 8).storeDict(dictionary).endCell();
|
|
106
|
+
}
|
|
107
|
+
function nftContentFromCell(cell) {
|
|
108
|
+
const slice = cell.beginParse();
|
|
109
|
+
const tag = slice.loadUint(8);
|
|
110
|
+
if (tag === 1) return {
|
|
111
|
+
type: "offchain",
|
|
112
|
+
uri: loadSnakeString(slice)
|
|
113
|
+
};
|
|
114
|
+
if (tag !== 0) throw new Error(`Unsupported NFT metadata content prefix: ${tag}`);
|
|
115
|
+
const dictionary = Dictionary.load(Dictionary.Keys.Buffer(32), onchainStringValue(), slice);
|
|
116
|
+
const keyByHash = new Map(NFT_ONCHAIN_CONTENT_KEYS.map((key) => [Buffer.from(sha256_sync(key)).toString("hex"), key]));
|
|
117
|
+
const data = {};
|
|
118
|
+
for (const [hash, value] of dictionary) {
|
|
119
|
+
const key = keyByHash.get(Buffer.from(hash).toString("hex"));
|
|
120
|
+
if (key) data[key] = value;
|
|
121
|
+
}
|
|
122
|
+
return {
|
|
123
|
+
type: "onchain",
|
|
124
|
+
data
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
function royaltyParamsToCell(royalty) {
|
|
128
|
+
invariant(royalty.royaltyFactor >= 0 && royalty.royaltyFactor < 2n ** 16n, "INVALID_TRANSACTION", "NFT royalty factor must fit in 16 bits");
|
|
129
|
+
invariant(royalty.royaltyBase > 0 && royalty.royaltyBase < 2n ** 16n, "INVALID_TRANSACTION", "NFT royalty base must fit in 16 bits and be positive");
|
|
130
|
+
return beginCell().storeUint(royalty.royaltyFactor, 16).storeUint(royalty.royaltyBase, 16).storeAddress(royalty.address).endCell();
|
|
131
|
+
}
|
|
132
|
+
function assertCell(value, message) {
|
|
133
|
+
invariant(value instanceof Cell, "INVALID_METADATA", message);
|
|
134
|
+
}
|
|
135
|
+
function storeNftContent(builder, content) {
|
|
136
|
+
return builder.storeRef(content instanceof Cell ? content : nftContentToCell(content));
|
|
137
|
+
}
|
|
138
|
+
function parseNftContentSlice(slice) {
|
|
139
|
+
return nftContentFromCell(slice.loadRef());
|
|
140
|
+
}
|
|
141
|
+
//#endregion
|
|
142
|
+
export { NFT_ONCHAIN_CONTENT_KEYS, assertCell, buildOnchainMetadata, nftContentFromCell, nftContentToCell, parseNftContentSlice, royaltyParamsToCell, storeNftContent };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { NFT_ONCHAIN_CONTENT_KEYS, NftContent, NftContentOffchain, NftContentOnchain, NftOnchainContentKey, RoyaltyParameters, assertCell, buildOnchainMetadata, nftContentFromCell, nftContentToCell, parseNftContentSlice, royaltyParamsToCell, storeNftContent } from "./content.mjs";
|
|
2
|
+
import { NFT_COLLECTION_OPCODES, NewNftItem, NftCollectionConfig, NftCollectionContract, NftCollectionData, buildNftBatchDeployBody, buildNftChangeOwnerBody, buildNftDeployItemBody, buildNftRoyaltyParamsBody, collectionConfigToCell } from "./collection.mjs";
|
|
3
|
+
import { NFT_IMPLEMENTATION_PROFILES, NftCollectionImplementationVersion, NftImplementationProfile, NftItemImplementationVersion } from "./versions.mjs";
|
|
4
|
+
import { Address, Cell, ContractProvider, Sender } from "@ton/core";
|
|
5
|
+
//#region src/nft/index.d.ts
|
|
6
|
+
export declare const NFT_OPCODES: {
|
|
7
|
+
readonly transfer: 1607220500;
|
|
8
|
+
readonly ownershipAssigned: 85167505;
|
|
9
|
+
readonly getStaticData: 801842850;
|
|
10
|
+
};
|
|
11
|
+
export interface NftTransferInput {
|
|
12
|
+
readonly newOwner: Address;
|
|
13
|
+
readonly responseDestination: Address;
|
|
14
|
+
readonly queryId?: bigint;
|
|
15
|
+
readonly forwardAmount?: bigint;
|
|
16
|
+
readonly customPayload?: Cell;
|
|
17
|
+
readonly forwardPayload?: Cell;
|
|
18
|
+
}
|
|
19
|
+
export interface NftItemData {
|
|
20
|
+
readonly initialized: boolean;
|
|
21
|
+
readonly index: bigint;
|
|
22
|
+
readonly collection: Address;
|
|
23
|
+
readonly owner: Address | null;
|
|
24
|
+
readonly content: Cell | null;
|
|
25
|
+
}
|
|
26
|
+
export declare class NftItemContract {
|
|
27
|
+
readonly address: Address;
|
|
28
|
+
private constructor();
|
|
29
|
+
static create(address: Address): NftItemContract;
|
|
30
|
+
getData(provider: ContractProvider): Promise<NftItemData>;
|
|
31
|
+
sendTransfer(provider: ContractProvider, via: Sender, input: NftTransferInput, value: bigint): Promise<void>;
|
|
32
|
+
}
|
|
33
|
+
export declare function buildNftTransferBody(input: NftTransferInput): Cell;
|
|
34
|
+
//#endregion
|
|
35
|
+
export { NFT_COLLECTION_OPCODES, NFT_IMPLEMENTATION_PROFILES, NFT_ONCHAIN_CONTENT_KEYS, NewNftItem, NftCollectionConfig, NftCollectionContract, NftCollectionData, NftCollectionImplementationVersion, NftContent, NftContentOffchain, NftContentOnchain, NftImplementationProfile, NftItemImplementationVersion, NftOnchainContentKey, RoyaltyParameters, assertCell, buildNftBatchDeployBody, buildNftChangeOwnerBody, buildNftDeployItemBody, buildNftRoyaltyParamsBody, buildOnchainMetadata, collectionConfigToCell, nftContentFromCell, nftContentToCell, parseNftContentSlice, royaltyParamsToCell, storeNftContent };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { invariant } from "../core/errors.mjs";
|
|
2
|
+
import { MAX_TON_COINS, assertTonAmount } from "../core/amount.mjs";
|
|
3
|
+
import { NFT_ONCHAIN_CONTENT_KEYS, assertCell, buildOnchainMetadata, nftContentFromCell, nftContentToCell, parseNftContentSlice, royaltyParamsToCell, storeNftContent } from "./content.mjs";
|
|
4
|
+
import { NFT_COLLECTION_OPCODES, NftCollectionContract, buildNftBatchDeployBody, buildNftChangeOwnerBody, buildNftDeployItemBody, buildNftRoyaltyParamsBody, collectionConfigToCell } from "./collection.mjs";
|
|
5
|
+
import { NFT_IMPLEMENTATION_PROFILES } from "./versions.mjs";
|
|
6
|
+
import { SendMode, beginCell } from "@ton/core";
|
|
7
|
+
//#region src/nft/index.ts
|
|
8
|
+
const NFT_OPCODES = {
|
|
9
|
+
transfer: 1607220500,
|
|
10
|
+
ownershipAssigned: 85167505,
|
|
11
|
+
getStaticData: 801842850
|
|
12
|
+
};
|
|
13
|
+
var NftItemContract = class NftItemContract {
|
|
14
|
+
address;
|
|
15
|
+
constructor(address) {
|
|
16
|
+
this.address = address;
|
|
17
|
+
}
|
|
18
|
+
static create(address) {
|
|
19
|
+
return new NftItemContract(address);
|
|
20
|
+
}
|
|
21
|
+
async getData(provider) {
|
|
22
|
+
const { stack } = await provider.get("get_nft_data", []);
|
|
23
|
+
return {
|
|
24
|
+
initialized: stack.readBigNumber() !== 0n,
|
|
25
|
+
index: stack.readBigNumber(),
|
|
26
|
+
collection: stack.readAddress(),
|
|
27
|
+
owner: stack.readAddressOpt(),
|
|
28
|
+
content: stack.readCellOpt()
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
async sendTransfer(provider, via, input, value) {
|
|
32
|
+
assertTonAmount(value, "NFT transfer value");
|
|
33
|
+
await provider.internal(via, {
|
|
34
|
+
value,
|
|
35
|
+
body: buildNftTransferBody(input),
|
|
36
|
+
sendMode: SendMode.PAY_GAS_SEPARATELY
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
function buildNftTransferBody(input) {
|
|
41
|
+
const queryId = input.queryId ?? 0n;
|
|
42
|
+
const forwardAmount = input.forwardAmount ?? 0n;
|
|
43
|
+
invariant(queryId >= 0n && queryId < 2n ** 64n, "INVALID_TRANSACTION", "Query id is out of range");
|
|
44
|
+
invariant(forwardAmount >= 0n && forwardAmount <= MAX_TON_COINS, "INVALID_AMOUNT", "Forward amount is outside the TON coin range");
|
|
45
|
+
const builder = beginCell().storeUint(NFT_OPCODES.transfer, 32).storeUint(queryId, 64).storeAddress(input.newOwner).storeAddress(input.responseDestination).storeMaybeRef(input.customPayload).storeCoins(forwardAmount);
|
|
46
|
+
if (input.forwardPayload) builder.storeBit(1).storeRef(input.forwardPayload);
|
|
47
|
+
else builder.storeBit(0);
|
|
48
|
+
return builder.endCell();
|
|
49
|
+
}
|
|
50
|
+
//#endregion
|
|
51
|
+
export { NFT_COLLECTION_OPCODES, NFT_IMPLEMENTATION_PROFILES, NFT_ONCHAIN_CONTENT_KEYS, NFT_OPCODES, NftCollectionContract, NftItemContract, assertCell, buildNftBatchDeployBody, buildNftChangeOwnerBody, buildNftDeployItemBody, buildNftRoyaltyParamsBody, buildNftTransferBody, buildOnchainMetadata, collectionConfigToCell, nftContentFromCell, nftContentToCell, parseNftContentSlice, royaltyParamsToCell, storeNftContent };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/nft/versions.d.ts
|
|
2
|
+
export type NftCollectionImplementationVersion = "default" | "compressed";
|
|
3
|
+
export type NftItemImplementationVersion = "default" | "sbt" | "single";
|
|
4
|
+
export interface NftImplementationProfile {
|
|
5
|
+
readonly version: NftCollectionImplementationVersion | NftItemImplementationVersion;
|
|
6
|
+
readonly transferable: boolean;
|
|
7
|
+
readonly supportsCollectionIndexing: boolean;
|
|
8
|
+
readonly supportsMerkleSelfDeployment: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare const NFT_IMPLEMENTATION_PROFILES: Readonly<Record<NftImplementationProfile["version"], NftImplementationProfile>>;
|
|
11
|
+
//#endregion
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
//#region src/nft/versions.ts
|
|
2
|
+
const NFT_IMPLEMENTATION_PROFILES = Object.freeze({
|
|
3
|
+
default: {
|
|
4
|
+
version: "default",
|
|
5
|
+
transferable: true,
|
|
6
|
+
supportsCollectionIndexing: true,
|
|
7
|
+
supportsMerkleSelfDeployment: false
|
|
8
|
+
},
|
|
9
|
+
compressed: {
|
|
10
|
+
version: "compressed",
|
|
11
|
+
transferable: true,
|
|
12
|
+
supportsCollectionIndexing: true,
|
|
13
|
+
supportsMerkleSelfDeployment: true
|
|
14
|
+
},
|
|
15
|
+
sbt: {
|
|
16
|
+
version: "sbt",
|
|
17
|
+
transferable: false,
|
|
18
|
+
supportsCollectionIndexing: true,
|
|
19
|
+
supportsMerkleSelfDeployment: false
|
|
20
|
+
},
|
|
21
|
+
single: {
|
|
22
|
+
version: "single",
|
|
23
|
+
transferable: true,
|
|
24
|
+
supportsCollectionIndexing: false,
|
|
25
|
+
supportsMerkleSelfDeployment: false
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
//#endregion
|
|
29
|
+
export { NFT_IMPLEMENTATION_PROFILES };
|