@interest-protocol/blast-coin-sdk 0.0.0-stage → 0.2.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/README.md +8 -2
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/template.d.ts +59 -0
- package/dist/template.d.ts.map +1 -0
- package/dist/template.js +207 -0
- package/dist/template.js.map +1 -0
- package/dist/transactions.d.ts +24 -0
- package/dist/transactions.d.ts.map +1 -0
- package/dist/transactions.js +39 -0
- package/dist/transactions.js.map +1 -0
- package/package.json +48 -4
- package/src/index.ts +2 -0
- package/src/template.ts +307 -0
- package/src/transactions.ts +63 -0
package/README.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @interest-protocol/blast-coin-sdk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The coin package in the [Blast SDK monorepo](https://github.com/interest-protocol/blast-v2-sdk).
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
npm install @interest-protocol/blast-coin-sdk
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
See the repository README and docs for usage, development, and release guidance.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { BytecodeTemplateInitOptions } from "@interest-protocol/blast-core/bytecode-template";
|
|
2
|
+
/**
|
|
3
|
+
* How the coin's supply may change after publication.
|
|
4
|
+
* - `mintable`: the `TreasuryCap` goes to `treasuryCapRecipient`, who may mint and burn.
|
|
5
|
+
* - `fixed`: the `TreasuryCap` is consumed; the supply never changes.
|
|
6
|
+
* - `burnOnly`: the `TreasuryCap` is consumed; any holder may burn through the `Currency`.
|
|
7
|
+
*/
|
|
8
|
+
export type CoinSupplyMode = {
|
|
9
|
+
kind: "mintable";
|
|
10
|
+
treasuryCapRecipient: string;
|
|
11
|
+
} | {
|
|
12
|
+
kind: "fixed";
|
|
13
|
+
} | {
|
|
14
|
+
kind: "burnOnly";
|
|
15
|
+
};
|
|
16
|
+
export type CoinTemplateOptions = {
|
|
17
|
+
/** ASCII printable; the Coin Registry rejects anything else. */
|
|
18
|
+
symbol: string;
|
|
19
|
+
name: string;
|
|
20
|
+
description: string;
|
|
21
|
+
iconUrl: string;
|
|
22
|
+
decimals: number;
|
|
23
|
+
/** Atomic units minted at publication; `0n` mints nothing (mintable only). */
|
|
24
|
+
initialSupply: bigint;
|
|
25
|
+
/** Receives the initial supply as one `Coin`. */
|
|
26
|
+
supplyRecipient: string;
|
|
27
|
+
supply: CoinSupplyMode;
|
|
28
|
+
/**
|
|
29
|
+
* Receives the `MetadataCap`; null deletes it, freezing the metadata for
|
|
30
|
+
* good.
|
|
31
|
+
*/
|
|
32
|
+
metadataCapRecipient: string | null;
|
|
33
|
+
/** Defaults to the lowercased symbol; the witness is the uppercased module name. */
|
|
34
|
+
moduleName?: string;
|
|
35
|
+
};
|
|
36
|
+
export type CoinTemplateIdentifiers = {
|
|
37
|
+
moduleName: string;
|
|
38
|
+
witnessName: string;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Initializes the bytecode-template WASM helper, shared with the Meme template.
|
|
42
|
+
* A browser can supply its WASM URL when the bundler cannot discover the
|
|
43
|
+
* package asset automatically.
|
|
44
|
+
*/
|
|
45
|
+
export declare function initializeCoinTemplate(options?: BytecodeTemplateInitOptions): Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* Builds the one-module standalone coin package of contracts ADR 0108. Its
|
|
48
|
+
* initializer creates the currency through the Coin Registry, mints
|
|
49
|
+
* `initialSupply` to `supplyRecipient`, settles the `TreasuryCap` by the
|
|
50
|
+
* supply mode, and delivers or deletes the `MetadataCap`. It depends only on
|
|
51
|
+
* the Move standard library and the Sui framework: Blast holds no authority
|
|
52
|
+
* over the coin, and it can never launch on Blast.
|
|
53
|
+
*/
|
|
54
|
+
export declare function buildCoinPackageBytecode(options: CoinTemplateOptions): Promise<Uint8Array>;
|
|
55
|
+
/** The coin module name and its uppercase one-time-witness name. */
|
|
56
|
+
export declare function deriveCoinTemplateIdentifiers(symbol: string, requestedModuleName?: string): CoinTemplateIdentifiers;
|
|
57
|
+
/** The packages a coin package links: the Move standard library and the Sui framework. */
|
|
58
|
+
export declare const COIN_PACKAGE_DEPENDENCIES: readonly ["0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000002"];
|
|
59
|
+
//# sourceMappingURL=template.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../src/template.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,iDAAiD,CAAC;AAkDnG;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,oBAAoB,EAAE,MAAM,CAAA;CAAE,GAClD;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC;AAEzB,MAAM,MAAM,mBAAmB,GAAG;IAChC,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,aAAa,EAAE,MAAM,CAAC;IACtB,iDAAiD;IACjD,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,cAAc,CAAC;IACvB;;;OAGG;IACH,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,oFAAoF;IACpF,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,CAAC,EAAE,2BAA2B,GACpC,OAAO,CAAC,IAAI,CAAC,CAEf;AAED;;;;;;;GAOG;AACH,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,UAAU,CAAC,CA4FrB;AAED,oEAAoE;AACpE,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,MAAM,EACd,mBAAmB,CAAC,EAAE,MAAM,GAC3B,uBAAuB,CAEzB;AAED,0FAA0F;AAC1F,eAAO,MAAM,yBAAyB,uJAG5B,CAAC"}
|
package/dist/template.js
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { assertIdentifierSlots, deriveTemplateIdentifiers, deserializeTemplate, initializeBytecodeTemplate, patchConstantSlots, requireNonEmptyString, requireString, } from "@interest-protocol/blast-core/bytecode-template";
|
|
2
|
+
import { requireU64 } from "@interest-protocol/blast-core/integers";
|
|
3
|
+
import { serialize, update_identifiers } from "@mysten/move-bytecode-template";
|
|
4
|
+
import { bcs } from "@mysten/sui/bcs";
|
|
5
|
+
import { fromBase64, isValidSuiAddress, MOVE_STDLIB_ADDRESS, normalizeSuiAddress, SUI_FRAMEWORK_ADDRESS, } from "@mysten/sui/utils";
|
|
6
|
+
// Built from contracts/sui/coin_template/sources/my_coin.move at contracts
|
|
7
|
+
// commit a1a8f6c9 with Sui CLI 1.77.2-51d177ad7d65; since 86d29e1 (ADR 0108)
|
|
8
|
+
// the source only moved its error constant, which reorders the pool. SHA-256:
|
|
9
|
+
// cdfdd72a9b0026afdbd9876a2d69f375ef02b5d39986b2e0c541413ac4de70cd
|
|
10
|
+
const TEMPLATE_BYTECODE_BASE64 = "oRzrCwcAAAUKAQAMAgwkAzA5BGkSBXuPAQeKArkCCMMEYAajBaECCsQHBQzJB78BABEBFAIHAggCFQIWAAICAAEEBwACAAwBAAECBQwBAAEDAQABAAEDAwwBAAEFBgIAAA0AAQAACQIBAAEXAwQAAhAJCgEAAwsPEAEAAwwPAQEAAw4OAQEAAw8OAQEAAxIHCAECBBMMAQEMCAYDBgkLCQ0HBgYGBAYJEQUGAggABwgGAA0IAAIIAQgBCAEIAQMFAgUBBQcIBgEKAgEIAQQGAgILBAEIAAsDAQgAAQgABwkAAggBCAEIAQgBBwgGAgsEAQkACwMBCQADBwsDAQkAAwcIBgELAgEJAAELAgEIAAIJAAUBCwMBCAACBwsEAQkACwMBCQACCwQBCQAHCAYBCwUBCQABCwUBCAAEQ29pbhNDdXJyZW5jeUluaXRpYWxpemVyB01ZX0NPSU4LTWV0YWRhdGFDYXAGU3RyaW5nC1RyZWFzdXJ5Q2FwCVR4Q29udGV4dARjb2luDWNvaW5fcmVnaXN0cnkbY3JlYXRlX2FuZF9kZWxpdmVyX2N1cnJlbmN5C2R1bW15X2ZpZWxkCGZpbmFsaXplIGZpbmFsaXplX2FuZF9kZWxldGVfbWV0YWRhdGFfY2FwBGluaXQabWFrZV9zdXBwbHlfYnVybl9vbmx5X2luaXQWbWFrZV9zdXBwbHlfZml4ZWRfaW5pdARtaW50B215X2NvaW4VbmV3X2N1cnJlbmN5X3dpdGhfb3R3D3B1YmxpY190cmFuc2ZlcgZzdHJpbmcIdHJhbnNmZXIKdHhfY29udGV4dAR1dGY4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACCgIFBENPSU4KAggHTXkgQ29pbgoCGBdBIGNvaW4gY3JlYXRlZCBvbiBCbGFzdAoCGxpodHRwczovL2JsYXN0LmZ1bi9jb2luLnBuZwIBCQMIAABkp7O24A0FIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF7hAgEBBSAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8qQEBAQUgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPnoKAhMSRUludmFsaWRTdXBwbHlNb2RlCgJDQlRoZSBzdXBwbHkgbW9kZSBtdXN0IGJlIDAgKG1pbnRhYmxlKSwgMSAoZml4ZWQpLCBvciAyIChidXJuLW9ubHkpLgACAQoBAAAAAAETCwAHBAcAEQIHARECBwIRAgcDEQIHBQcGBwcHCAcJBwoLAREBAgABAAAABUQKCDECJQQFBQkLDAEGDAALAFIAAMAnCwALAQsCCwMLBAsFCgw4AAwQDA8KBgYAAAAAAAAAACQEHQ0QCwYKDDgBCwc4AgsIDA4ODgwNCg0UMQAhBCwLDQELEAsJOAMFOAsNFDEBIQQ1DQ8LEDgEBTgNDwsQOAULCgRACw8LDDgGCws4BwVDCw8LDDgIAgAA";
|
|
11
|
+
const LABEL = "coin template";
|
|
12
|
+
/** The template's placeholder module and one-time-witness names. */
|
|
13
|
+
const PLACEHOLDERS = ["MY_COIN", "my_coin"];
|
|
14
|
+
const defaults = {
|
|
15
|
+
symbol: bcs.string().serialize("COIN").toBytes(),
|
|
16
|
+
name: bcs.string().serialize("My Coin").toBytes(),
|
|
17
|
+
description: bcs.string().serialize("A coin created on Blast").toBytes(),
|
|
18
|
+
iconUrl: bcs.string().serialize("https://blast.fun/coin.png").toBytes(),
|
|
19
|
+
decimals: bcs.u8().serialize(9).toBytes(),
|
|
20
|
+
initialSupply: bcs.u64().serialize(1000000000000000000n).toBytes(),
|
|
21
|
+
supplyRecipient: bcs.Address.serialize("0x5ee1").toBytes(),
|
|
22
|
+
supplyMode: bcs.u8().serialize(1).toBytes(),
|
|
23
|
+
treasuryCapRecipient: bcs.Address.serialize("0x7ca9").toBytes(),
|
|
24
|
+
metadataMutable: bcs.bool().serialize(true).toBytes(),
|
|
25
|
+
metadataCapRecipient: bcs.Address.serialize("0x3e7a").toBytes(),
|
|
26
|
+
};
|
|
27
|
+
/** `SUPPLY_MODE` values the template's initializer accepts. */
|
|
28
|
+
const SUPPLY_MODES = { mintable: 0, fixed: 1, burnOnly: 2 };
|
|
29
|
+
/**
|
|
30
|
+
* Initializes the bytecode-template WASM helper, shared with the Meme template.
|
|
31
|
+
* A browser can supply its WASM URL when the bundler cannot discover the
|
|
32
|
+
* package asset automatically.
|
|
33
|
+
*/
|
|
34
|
+
export function initializeCoinTemplate(options) {
|
|
35
|
+
return initializeBytecodeTemplate(options);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Builds the one-module standalone coin package of contracts ADR 0108. Its
|
|
39
|
+
* initializer creates the currency through the Coin Registry, mints
|
|
40
|
+
* `initialSupply` to `supplyRecipient`, settles the `TreasuryCap` by the
|
|
41
|
+
* supply mode, and delivers or deletes the `MetadataCap`. It depends only on
|
|
42
|
+
* the Move standard library and the Sui framework: Blast holds no authority
|
|
43
|
+
* over the coin, and it can never launch on Blast.
|
|
44
|
+
*/
|
|
45
|
+
export async function buildCoinPackageBytecode(options) {
|
|
46
|
+
const settings = validateCoinOptions(options);
|
|
47
|
+
const identifiers = deriveCoinTemplateIdentifiers(settings.symbol, options.moduleName);
|
|
48
|
+
await initializeCoinTemplate();
|
|
49
|
+
const compiled = deserializeTemplate(LABEL, fromBase64(TEMPLATE_BYTECODE_BASE64));
|
|
50
|
+
assertIdentifierSlots(LABEL, compiled, PLACEHOLDERS, identifiers);
|
|
51
|
+
patchConstantSlots(LABEL, compiled, [
|
|
52
|
+
{
|
|
53
|
+
name: "symbol",
|
|
54
|
+
type: "Vector(U8)",
|
|
55
|
+
expected: defaults.symbol,
|
|
56
|
+
replacement: bcs.string().serialize(settings.symbol).toBytes(),
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: "name",
|
|
60
|
+
type: "Vector(U8)",
|
|
61
|
+
expected: defaults.name,
|
|
62
|
+
replacement: bcs.string().serialize(settings.name).toBytes(),
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: "description",
|
|
66
|
+
type: "Vector(U8)",
|
|
67
|
+
expected: defaults.description,
|
|
68
|
+
replacement: bcs.string().serialize(settings.description).toBytes(),
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: "iconUrl",
|
|
72
|
+
type: "Vector(U8)",
|
|
73
|
+
expected: defaults.iconUrl,
|
|
74
|
+
replacement: bcs.string().serialize(settings.iconUrl).toBytes(),
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: "decimals",
|
|
78
|
+
type: "U8",
|
|
79
|
+
expected: defaults.decimals,
|
|
80
|
+
replacement: bcs.u8().serialize(settings.decimals).toBytes(),
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: "initialSupply",
|
|
84
|
+
type: "U64",
|
|
85
|
+
expected: defaults.initialSupply,
|
|
86
|
+
replacement: bcs.u64().serialize(settings.initialSupply).toBytes(),
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: "supplyRecipient",
|
|
90
|
+
type: "Address",
|
|
91
|
+
expected: defaults.supplyRecipient,
|
|
92
|
+
replacement: bcs.Address.serialize(settings.supplyRecipient).toBytes(),
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
name: "supplyMode",
|
|
96
|
+
type: "U8",
|
|
97
|
+
expected: defaults.supplyMode,
|
|
98
|
+
replacement: bcs.u8().serialize(settings.supplyMode).toBytes(),
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
name: "treasuryCapRecipient",
|
|
102
|
+
type: "Address",
|
|
103
|
+
expected: defaults.treasuryCapRecipient,
|
|
104
|
+
replacement: bcs.Address.serialize(settings.treasuryCapRecipient).toBytes(),
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
name: "metadataMutable",
|
|
108
|
+
type: "Bool",
|
|
109
|
+
expected: defaults.metadataMutable,
|
|
110
|
+
replacement: bcs.bool().serialize(settings.metadataMutable).toBytes(),
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: "metadataCapRecipient",
|
|
114
|
+
type: "Address",
|
|
115
|
+
expected: defaults.metadataCapRecipient,
|
|
116
|
+
replacement: bcs.Address.serialize(settings.metadataCapRecipient).toBytes(),
|
|
117
|
+
},
|
|
118
|
+
]);
|
|
119
|
+
const bytecode = update_identifiers(serialize(compiled), {
|
|
120
|
+
MY_COIN: identifiers.witnessName,
|
|
121
|
+
my_coin: identifiers.moduleName,
|
|
122
|
+
});
|
|
123
|
+
assertCoinTemplateWiring(bytecode, identifiers);
|
|
124
|
+
return bytecode;
|
|
125
|
+
}
|
|
126
|
+
/** The coin module name and its uppercase one-time-witness name. */
|
|
127
|
+
export function deriveCoinTemplateIdentifiers(symbol, requestedModuleName) {
|
|
128
|
+
return deriveTemplateIdentifiers(symbol, requestedModuleName);
|
|
129
|
+
}
|
|
130
|
+
/** The packages a coin package links: the Move standard library and the Sui framework. */
|
|
131
|
+
export const COIN_PACKAGE_DEPENDENCIES = [
|
|
132
|
+
MOVE_STDLIB_ADDRESS,
|
|
133
|
+
SUI_FRAMEWORK_ADDRESS,
|
|
134
|
+
];
|
|
135
|
+
/**
|
|
136
|
+
* Checks every option before patching, so the initializer cannot abort at
|
|
137
|
+
* publication: a printable symbol, a `u8` precision, a `u64` supply that is
|
|
138
|
+
* nonzero unless mintable, and nonzero recipients. A recipient the mode
|
|
139
|
+
* leaves unused keeps the template default.
|
|
140
|
+
*/
|
|
141
|
+
function validateCoinOptions(options) {
|
|
142
|
+
if (typeof options !== "object" || options === null) {
|
|
143
|
+
throw new TypeError("coin template options are required");
|
|
144
|
+
}
|
|
145
|
+
const symbol = requireNonEmptyString("symbol", options.symbol);
|
|
146
|
+
if (!/^[\x20-\x7e]+$/.test(symbol)) {
|
|
147
|
+
throw new RangeError("symbol must be ASCII printable");
|
|
148
|
+
}
|
|
149
|
+
const { decimals } = options;
|
|
150
|
+
if (!Number.isInteger(decimals) || decimals < 0 || decimals > 255) {
|
|
151
|
+
throw new RangeError("decimals must be a u8");
|
|
152
|
+
}
|
|
153
|
+
if (typeof options.initialSupply !== "bigint") {
|
|
154
|
+
throw new TypeError("initialSupply must be a bigint");
|
|
155
|
+
}
|
|
156
|
+
const initialSupply = requireU64("initialSupply", options.initialSupply);
|
|
157
|
+
const { supply } = options;
|
|
158
|
+
const supplyMode = SUPPLY_MODES[supply?.kind];
|
|
159
|
+
if (supplyMode === undefined) {
|
|
160
|
+
throw new TypeError("supply.kind must be mintable, fixed, or burnOnly");
|
|
161
|
+
}
|
|
162
|
+
if (supply.kind !== "mintable" && initialSupply === 0n) {
|
|
163
|
+
throw new RangeError("a fixed or burn-only supply must mint a nonzero initial supply");
|
|
164
|
+
}
|
|
165
|
+
const metadataMutable = options.metadataCapRecipient !== null;
|
|
166
|
+
return {
|
|
167
|
+
symbol,
|
|
168
|
+
name: requireNonEmptyString("name", options.name),
|
|
169
|
+
description: requireString("description", options.description),
|
|
170
|
+
iconUrl: requireString("iconUrl", options.iconUrl),
|
|
171
|
+
decimals,
|
|
172
|
+
initialSupply,
|
|
173
|
+
supplyRecipient: initialSupply
|
|
174
|
+
? recipient("supplyRecipient", options.supplyRecipient)
|
|
175
|
+
: normalizeSuiAddress("0x5ee1"),
|
|
176
|
+
supplyMode,
|
|
177
|
+
treasuryCapRecipient: supply.kind === "mintable"
|
|
178
|
+
? recipient("supply.treasuryCapRecipient", supply.treasuryCapRecipient)
|
|
179
|
+
: normalizeSuiAddress("0x7ca9"),
|
|
180
|
+
metadataMutable,
|
|
181
|
+
metadataCapRecipient: metadataMutable
|
|
182
|
+
? recipient("metadataCapRecipient", options.metadataCapRecipient ?? "")
|
|
183
|
+
: normalizeSuiAddress("0x3e7a"),
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
function recipient(name, address) {
|
|
187
|
+
if (typeof address !== "string") {
|
|
188
|
+
throw new TypeError(`${name} must be a string`);
|
|
189
|
+
}
|
|
190
|
+
const normalized = normalizeSuiAddress(address);
|
|
191
|
+
if (!isValidSuiAddress(normalized) || BigInt(normalized) === 0n) {
|
|
192
|
+
throw new RangeError(`${name} must be a nonzero Sui address`);
|
|
193
|
+
}
|
|
194
|
+
return normalized;
|
|
195
|
+
}
|
|
196
|
+
function assertCoinTemplateWiring(bytecode, identifiers) {
|
|
197
|
+
const compiled = deserializeTemplate(LABEL, bytecode);
|
|
198
|
+
if (!compiled.identifiers.includes(identifiers.moduleName) ||
|
|
199
|
+
!compiled.identifiers.includes(identifiers.witnessName)) {
|
|
200
|
+
throw new TypeError("coin template identifiers were not patched");
|
|
201
|
+
}
|
|
202
|
+
const systemAddresses = new Set([normalizeSuiAddress("0x0"), ...COIN_PACKAGE_DEPENDENCIES].map((address) => normalizeSuiAddress(address).slice(2)));
|
|
203
|
+
if (!compiled.address_identifiers.every((address) => systemAddresses.has(address))) {
|
|
204
|
+
throw new TypeError("coin template must link only 0x1 and 0x2");
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
//# sourceMappingURL=template.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template.js","sourceRoot":"","sources":["../src/template.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { TransactionObjectInput } from "@mysten/sui/transactions";
|
|
2
|
+
import { Transaction } from "@mysten/sui/transactions";
|
|
3
|
+
import type { CoinTemplateOptions } from "./template.ts";
|
|
4
|
+
export type CoinPublication = CoinTemplateOptions & {
|
|
5
|
+
/**
|
|
6
|
+
* Receives the package's `UpgradeCap`; null makes the package immutable in
|
|
7
|
+
* the same transaction, so nobody can ever change the coin's module.
|
|
8
|
+
*/
|
|
9
|
+
upgradeCapRecipient: string | null;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Publishes a standalone coin from the coin template (contracts ADR 0108).
|
|
13
|
+
* The initializer runs at publication and delivers the supply and the
|
|
14
|
+
* capabilities to the recipients `options` names; its `Currency` goes to the
|
|
15
|
+
* Coin Registry address, where anyone may share it with
|
|
16
|
+
* `coin_registry::finalize_registration` in a later transaction.
|
|
17
|
+
*/
|
|
18
|
+
export declare function publishCoin(options: CoinPublication): Transaction;
|
|
19
|
+
/** Shares a published coin's pending Currency from the Coin Registry address. */
|
|
20
|
+
export declare function finalizeCoinRegistration(tx: Transaction, options: {
|
|
21
|
+
coinType: string;
|
|
22
|
+
currency: TransactionObjectInput;
|
|
23
|
+
}): void;
|
|
24
|
+
//# sourceMappingURL=transactions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transactions.d.ts","sourceRoot":"","sources":["../src/transactions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAOvD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAMzD,MAAM,MAAM,eAAe,GAAG,mBAAmB,GAAG;IAClD;;;OAGG;IACH,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,eAAe,GAAG,WAAW,CAqBjE;AAED,iFAAiF;AACjF,wBAAgB,wBAAwB,CACtC,EAAE,EAAE,WAAW,EACf,OAAO,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,sBAAsB,CAAA;CAAE,GAC9D,IAAI,CAMN"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Transaction } from "@mysten/sui/transactions";
|
|
2
|
+
import { normalizeStructTag, normalizeSuiAddress, SUI_FRAMEWORK_ADDRESS, } from "@mysten/sui/utils";
|
|
3
|
+
import { buildCoinPackageBytecode, COIN_PACKAGE_DEPENDENCIES, } from "./template.js";
|
|
4
|
+
/**
|
|
5
|
+
* Publishes a standalone coin from the coin template (contracts ADR 0108).
|
|
6
|
+
* The initializer runs at publication and delivers the supply and the
|
|
7
|
+
* capabilities to the recipients `options` names; its `Currency` goes to the
|
|
8
|
+
* Coin Registry address, where anyone may share it with
|
|
9
|
+
* `coin_registry::finalize_registration` in a later transaction.
|
|
10
|
+
*/
|
|
11
|
+
export function publishCoin(options) {
|
|
12
|
+
const tx = new Transaction();
|
|
13
|
+
const upgradeCap = tx.add(async (innerTx) => {
|
|
14
|
+
const module = await buildCoinPackageBytecode(options);
|
|
15
|
+
return innerTx.publish({
|
|
16
|
+
modules: [Array.from(module)],
|
|
17
|
+
dependencies: [...COIN_PACKAGE_DEPENDENCIES],
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
if (options.upgradeCapRecipient === null) {
|
|
21
|
+
tx.moveCall({
|
|
22
|
+
target: `${SUI_FRAMEWORK_ADDRESS}::package::make_immutable`,
|
|
23
|
+
arguments: [upgradeCap],
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
tx.transferObjects([upgradeCap], normalizeSuiAddress(options.upgradeCapRecipient));
|
|
28
|
+
}
|
|
29
|
+
return tx;
|
|
30
|
+
}
|
|
31
|
+
/** Shares a published coin's pending Currency from the Coin Registry address. */
|
|
32
|
+
export function finalizeCoinRegistration(tx, options) {
|
|
33
|
+
tx.moveCall({
|
|
34
|
+
target: `${SUI_FRAMEWORK_ADDRESS}::coin_registry::finalize_registration`,
|
|
35
|
+
typeArguments: [normalizeStructTag(options.coinType)],
|
|
36
|
+
arguments: [tx.object("0xc"), tx.object(options.currency)],
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=transactions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transactions.js","sourceRoot":"","sources":["../src/transactions.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,eAAe,CAAC;AAUvB;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,OAAwB;IAClD,MAAM,EAAE,GAAG,IAAI,WAAW,EAAE,CAAC;IAC7B,MAAM,UAAU,GAAG,EAAE,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;QAC1C,MAAM,MAAM,GAAG,MAAM,wBAAwB,CAAC,OAAO,CAAC,CAAC;QACvD,OAAO,OAAO,CAAC,OAAO,CAAC;YACrB,OAAO,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC7B,YAAY,EAAE,CAAC,GAAG,yBAAyB,CAAC;SAC7C,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IACH,IAAI,OAAO,CAAC,mBAAmB,KAAK,IAAI,EAAE,CAAC;QACzC,EAAE,CAAC,QAAQ,CAAC;YACV,MAAM,EAAE,GAAG,qBAAqB,2BAA2B;YAC3D,SAAS,EAAE,CAAC,UAAU,CAAC;SACxB,CAAC,CAAC;IACL,CAAC;SAAM,CAAC;QACN,EAAE,CAAC,eAAe,CAChB,CAAC,UAAU,CAAC,EACZ,mBAAmB,CAAC,OAAO,CAAC,mBAAmB,CAAC,CACjD,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,wBAAwB,CACtC,EAAe,EACf,OAA+D;IAE/D,EAAE,CAAC,QAAQ,CAAC;QACV,MAAM,EAAE,GAAG,qBAAqB,wCAAwC;QACxE,aAAa,EAAE,CAAC,kBAAkB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACrD,SAAS,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;KAC3D,CAAC,CAAC;AACL,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,50 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@interest-protocol/blast-coin-sdk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Blast coin SDK",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/interest-protocol/blast-v2-sdk.git",
|
|
9
|
+
"directory": "packages/coin"
|
|
10
|
+
},
|
|
11
|
+
"sideEffects": false,
|
|
12
|
+
"files": [
|
|
13
|
+
"dist",
|
|
14
|
+
"src"
|
|
15
|
+
],
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"default": "./dist/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./template": {
|
|
22
|
+
"types": "./dist/template.d.ts",
|
|
23
|
+
"default": "./dist/template.js"
|
|
24
|
+
},
|
|
25
|
+
"./transactions": {
|
|
26
|
+
"types": "./dist/transactions.d.ts",
|
|
27
|
+
"default": "./dist/transactions.js"
|
|
28
|
+
},
|
|
29
|
+
"./package.json": "./package.json"
|
|
30
|
+
},
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": ">=22"
|
|
33
|
+
},
|
|
34
|
+
"scripts": {
|
|
35
|
+
"build": "node --eval \"fs.rmSync('dist', { recursive: true, force: true })\" && tsc -p tsconfig.json",
|
|
36
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
37
|
+
"check:package": "publint --strict && attw --pack . --profile esm-only",
|
|
38
|
+
"prepack": "npm run build"
|
|
39
|
+
},
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@interest-protocol/blast-core": "0.2.0"
|
|
45
|
+
},
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"@mysten/move-bytecode-template": "^0.4.1",
|
|
48
|
+
"@mysten/sui": "^2.26.2"
|
|
49
|
+
}
|
|
50
|
+
}
|
package/src/index.ts
ADDED
package/src/template.ts
ADDED
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
import type { BytecodeTemplateInitOptions } from "@interest-protocol/blast-core/bytecode-template";
|
|
2
|
+
import {
|
|
3
|
+
assertIdentifierSlots,
|
|
4
|
+
deriveTemplateIdentifiers,
|
|
5
|
+
deserializeTemplate,
|
|
6
|
+
initializeBytecodeTemplate,
|
|
7
|
+
patchConstantSlots,
|
|
8
|
+
requireNonEmptyString,
|
|
9
|
+
requireString,
|
|
10
|
+
} from "@interest-protocol/blast-core/bytecode-template";
|
|
11
|
+
import { requireU64 } from "@interest-protocol/blast-core/integers";
|
|
12
|
+
import { serialize, update_identifiers } from "@mysten/move-bytecode-template";
|
|
13
|
+
import { bcs } from "@mysten/sui/bcs";
|
|
14
|
+
import {
|
|
15
|
+
fromBase64,
|
|
16
|
+
isValidSuiAddress,
|
|
17
|
+
MOVE_STDLIB_ADDRESS,
|
|
18
|
+
normalizeSuiAddress,
|
|
19
|
+
SUI_FRAMEWORK_ADDRESS,
|
|
20
|
+
} from "@mysten/sui/utils";
|
|
21
|
+
|
|
22
|
+
// Built from contracts/sui/coin_template/sources/my_coin.move at contracts
|
|
23
|
+
// commit a1a8f6c9 with Sui CLI 1.77.2-51d177ad7d65; since 86d29e1 (ADR 0108)
|
|
24
|
+
// the source only moved its error constant, which reorders the pool. SHA-256:
|
|
25
|
+
// cdfdd72a9b0026afdbd9876a2d69f375ef02b5d39986b2e0c541413ac4de70cd
|
|
26
|
+
const TEMPLATE_BYTECODE_BASE64 =
|
|
27
|
+
"oRzrCwcAAAUKAQAMAgwkAzA5BGkSBXuPAQeKArkCCMMEYAajBaECCsQHBQzJB78BABEBFAIHAggCFQIWAAICAAEEBwACAAwBAAECBQwBAAEDAQABAAEDAwwBAAEFBgIAAA0AAQAACQIBAAEXAwQAAhAJCgEAAwsPEAEAAwwPAQEAAw4OAQEAAw8OAQEAAxIHCAECBBMMAQEMCAYDBgkLCQ0HBgYGBAYJEQUGAggABwgGAA0IAAIIAQgBCAEIAQMFAgUBBQcIBgEKAgEIAQQGAgILBAEIAAsDAQgAAQgABwkAAggBCAEIAQgBBwgGAgsEAQkACwMBCQADBwsDAQkAAwcIBgELAgEJAAELAgEIAAIJAAUBCwMBCAACBwsEAQkACwMBCQACCwQBCQAHCAYBCwUBCQABCwUBCAAEQ29pbhNDdXJyZW5jeUluaXRpYWxpemVyB01ZX0NPSU4LTWV0YWRhdGFDYXAGU3RyaW5nC1RyZWFzdXJ5Q2FwCVR4Q29udGV4dARjb2luDWNvaW5fcmVnaXN0cnkbY3JlYXRlX2FuZF9kZWxpdmVyX2N1cnJlbmN5C2R1bW15X2ZpZWxkCGZpbmFsaXplIGZpbmFsaXplX2FuZF9kZWxldGVfbWV0YWRhdGFfY2FwBGluaXQabWFrZV9zdXBwbHlfYnVybl9vbmx5X2luaXQWbWFrZV9zdXBwbHlfZml4ZWRfaW5pdARtaW50B215X2NvaW4VbmV3X2N1cnJlbmN5X3dpdGhfb3R3D3B1YmxpY190cmFuc2ZlcgZzdHJpbmcIdHJhbnNmZXIKdHhfY29udGV4dAR1dGY4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACCgIFBENPSU4KAggHTXkgQ29pbgoCGBdBIGNvaW4gY3JlYXRlZCBvbiBCbGFzdAoCGxpodHRwczovL2JsYXN0LmZ1bi9jb2luLnBuZwIBCQMIAABkp7O24A0FIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF7hAgEBBSAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8qQEBAQUgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPnoKAhMSRUludmFsaWRTdXBwbHlNb2RlCgJDQlRoZSBzdXBwbHkgbW9kZSBtdXN0IGJlIDAgKG1pbnRhYmxlKSwgMSAoZml4ZWQpLCBvciAyIChidXJuLW9ubHkpLgACAQoBAAAAAAETCwAHBAcAEQIHARECBwIRAgcDEQIHBQcGBwcHCAcJBwoLAREBAgABAAAABUQKCDECJQQFBQkLDAEGDAALAFIAAMAnCwALAQsCCwMLBAsFCgw4AAwQDA8KBgYAAAAAAAAAACQEHQ0QCwYKDDgBCwc4AgsIDA4ODgwNCg0UMQAhBCwLDQELEAsJOAMFOAsNFDEBIQQ1DQ8LEDgEBTgNDwsQOAULCgRACw8LDDgGCws4BwVDCw8LDDgIAgAA";
|
|
28
|
+
|
|
29
|
+
const LABEL = "coin template";
|
|
30
|
+
|
|
31
|
+
/** The template's placeholder module and one-time-witness names. */
|
|
32
|
+
const PLACEHOLDERS = ["MY_COIN", "my_coin"] as const;
|
|
33
|
+
|
|
34
|
+
const defaults = {
|
|
35
|
+
symbol: bcs.string().serialize("COIN").toBytes(),
|
|
36
|
+
name: bcs.string().serialize("My Coin").toBytes(),
|
|
37
|
+
description: bcs.string().serialize("A coin created on Blast").toBytes(),
|
|
38
|
+
iconUrl: bcs.string().serialize("https://blast.fun/coin.png").toBytes(),
|
|
39
|
+
decimals: bcs.u8().serialize(9).toBytes(),
|
|
40
|
+
initialSupply: bcs.u64().serialize(1_000_000_000_000_000_000n).toBytes(),
|
|
41
|
+
supplyRecipient: bcs.Address.serialize("0x5ee1").toBytes(),
|
|
42
|
+
supplyMode: bcs.u8().serialize(1).toBytes(),
|
|
43
|
+
treasuryCapRecipient: bcs.Address.serialize("0x7ca9").toBytes(),
|
|
44
|
+
metadataMutable: bcs.bool().serialize(true).toBytes(),
|
|
45
|
+
metadataCapRecipient: bcs.Address.serialize("0x3e7a").toBytes(),
|
|
46
|
+
} as const;
|
|
47
|
+
|
|
48
|
+
/** `SUPPLY_MODE` values the template's initializer accepts. */
|
|
49
|
+
const SUPPLY_MODES = { mintable: 0, fixed: 1, burnOnly: 2 } as const;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* How the coin's supply may change after publication.
|
|
53
|
+
* - `mintable`: the `TreasuryCap` goes to `treasuryCapRecipient`, who may mint and burn.
|
|
54
|
+
* - `fixed`: the `TreasuryCap` is consumed; the supply never changes.
|
|
55
|
+
* - `burnOnly`: the `TreasuryCap` is consumed; any holder may burn through the `Currency`.
|
|
56
|
+
*/
|
|
57
|
+
export type CoinSupplyMode =
|
|
58
|
+
| { kind: "mintable"; treasuryCapRecipient: string }
|
|
59
|
+
| { kind: "fixed" }
|
|
60
|
+
| { kind: "burnOnly" };
|
|
61
|
+
|
|
62
|
+
export type CoinTemplateOptions = {
|
|
63
|
+
/** ASCII printable; the Coin Registry rejects anything else. */
|
|
64
|
+
symbol: string;
|
|
65
|
+
name: string;
|
|
66
|
+
description: string;
|
|
67
|
+
iconUrl: string;
|
|
68
|
+
decimals: number;
|
|
69
|
+
/** Atomic units minted at publication; `0n` mints nothing (mintable only). */
|
|
70
|
+
initialSupply: bigint;
|
|
71
|
+
/** Receives the initial supply as one `Coin`. */
|
|
72
|
+
supplyRecipient: string;
|
|
73
|
+
supply: CoinSupplyMode;
|
|
74
|
+
/**
|
|
75
|
+
* Receives the `MetadataCap`; null deletes it, freezing the metadata for
|
|
76
|
+
* good.
|
|
77
|
+
*/
|
|
78
|
+
metadataCapRecipient: string | null;
|
|
79
|
+
/** Defaults to the lowercased symbol; the witness is the uppercased module name. */
|
|
80
|
+
moduleName?: string;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export type CoinTemplateIdentifiers = {
|
|
84
|
+
moduleName: string;
|
|
85
|
+
witnessName: string;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Initializes the bytecode-template WASM helper, shared with the Meme template.
|
|
90
|
+
* A browser can supply its WASM URL when the bundler cannot discover the
|
|
91
|
+
* package asset automatically.
|
|
92
|
+
*/
|
|
93
|
+
export function initializeCoinTemplate(
|
|
94
|
+
options?: BytecodeTemplateInitOptions,
|
|
95
|
+
): Promise<void> {
|
|
96
|
+
return initializeBytecodeTemplate(options);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Builds the one-module standalone coin package of contracts ADR 0108. Its
|
|
101
|
+
* initializer creates the currency through the Coin Registry, mints
|
|
102
|
+
* `initialSupply` to `supplyRecipient`, settles the `TreasuryCap` by the
|
|
103
|
+
* supply mode, and delivers or deletes the `MetadataCap`. It depends only on
|
|
104
|
+
* the Move standard library and the Sui framework: Blast holds no authority
|
|
105
|
+
* over the coin, and it can never launch on Blast.
|
|
106
|
+
*/
|
|
107
|
+
export async function buildCoinPackageBytecode(
|
|
108
|
+
options: CoinTemplateOptions,
|
|
109
|
+
): Promise<Uint8Array> {
|
|
110
|
+
const settings = validateCoinOptions(options);
|
|
111
|
+
const identifiers = deriveCoinTemplateIdentifiers(
|
|
112
|
+
settings.symbol,
|
|
113
|
+
options.moduleName,
|
|
114
|
+
);
|
|
115
|
+
await initializeCoinTemplate();
|
|
116
|
+
|
|
117
|
+
const compiled = deserializeTemplate(
|
|
118
|
+
LABEL,
|
|
119
|
+
fromBase64(TEMPLATE_BYTECODE_BASE64),
|
|
120
|
+
);
|
|
121
|
+
assertIdentifierSlots(LABEL, compiled, PLACEHOLDERS, identifiers);
|
|
122
|
+
patchConstantSlots(LABEL, compiled, [
|
|
123
|
+
{
|
|
124
|
+
name: "symbol",
|
|
125
|
+
type: "Vector(U8)",
|
|
126
|
+
expected: defaults.symbol,
|
|
127
|
+
replacement: bcs.string().serialize(settings.symbol).toBytes(),
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
name: "name",
|
|
131
|
+
type: "Vector(U8)",
|
|
132
|
+
expected: defaults.name,
|
|
133
|
+
replacement: bcs.string().serialize(settings.name).toBytes(),
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
name: "description",
|
|
137
|
+
type: "Vector(U8)",
|
|
138
|
+
expected: defaults.description,
|
|
139
|
+
replacement: bcs.string().serialize(settings.description).toBytes(),
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
name: "iconUrl",
|
|
143
|
+
type: "Vector(U8)",
|
|
144
|
+
expected: defaults.iconUrl,
|
|
145
|
+
replacement: bcs.string().serialize(settings.iconUrl).toBytes(),
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
name: "decimals",
|
|
149
|
+
type: "U8",
|
|
150
|
+
expected: defaults.decimals,
|
|
151
|
+
replacement: bcs.u8().serialize(settings.decimals).toBytes(),
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
name: "initialSupply",
|
|
155
|
+
type: "U64",
|
|
156
|
+
expected: defaults.initialSupply,
|
|
157
|
+
replacement: bcs.u64().serialize(settings.initialSupply).toBytes(),
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
name: "supplyRecipient",
|
|
161
|
+
type: "Address",
|
|
162
|
+
expected: defaults.supplyRecipient,
|
|
163
|
+
replacement: bcs.Address.serialize(settings.supplyRecipient).toBytes(),
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
name: "supplyMode",
|
|
167
|
+
type: "U8",
|
|
168
|
+
expected: defaults.supplyMode,
|
|
169
|
+
replacement: bcs.u8().serialize(settings.supplyMode).toBytes(),
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
name: "treasuryCapRecipient",
|
|
173
|
+
type: "Address",
|
|
174
|
+
expected: defaults.treasuryCapRecipient,
|
|
175
|
+
replacement: bcs.Address.serialize(
|
|
176
|
+
settings.treasuryCapRecipient,
|
|
177
|
+
).toBytes(),
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
name: "metadataMutable",
|
|
181
|
+
type: "Bool",
|
|
182
|
+
expected: defaults.metadataMutable,
|
|
183
|
+
replacement: bcs.bool().serialize(settings.metadataMutable).toBytes(),
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
name: "metadataCapRecipient",
|
|
187
|
+
type: "Address",
|
|
188
|
+
expected: defaults.metadataCapRecipient,
|
|
189
|
+
replacement: bcs.Address.serialize(
|
|
190
|
+
settings.metadataCapRecipient,
|
|
191
|
+
).toBytes(),
|
|
192
|
+
},
|
|
193
|
+
]);
|
|
194
|
+
|
|
195
|
+
const bytecode = update_identifiers(serialize(compiled), {
|
|
196
|
+
MY_COIN: identifiers.witnessName,
|
|
197
|
+
my_coin: identifiers.moduleName,
|
|
198
|
+
});
|
|
199
|
+
assertCoinTemplateWiring(bytecode, identifiers);
|
|
200
|
+
return bytecode;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/** The coin module name and its uppercase one-time-witness name. */
|
|
204
|
+
export function deriveCoinTemplateIdentifiers(
|
|
205
|
+
symbol: string,
|
|
206
|
+
requestedModuleName?: string,
|
|
207
|
+
): CoinTemplateIdentifiers {
|
|
208
|
+
return deriveTemplateIdentifiers(symbol, requestedModuleName);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/** The packages a coin package links: the Move standard library and the Sui framework. */
|
|
212
|
+
export const COIN_PACKAGE_DEPENDENCIES = [
|
|
213
|
+
MOVE_STDLIB_ADDRESS,
|
|
214
|
+
SUI_FRAMEWORK_ADDRESS,
|
|
215
|
+
] as const;
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Checks every option before patching, so the initializer cannot abort at
|
|
219
|
+
* publication: a printable symbol, a `u8` precision, a `u64` supply that is
|
|
220
|
+
* nonzero unless mintable, and nonzero recipients. A recipient the mode
|
|
221
|
+
* leaves unused keeps the template default.
|
|
222
|
+
*/
|
|
223
|
+
function validateCoinOptions(options: CoinTemplateOptions) {
|
|
224
|
+
if (typeof options !== "object" || options === null) {
|
|
225
|
+
throw new TypeError("coin template options are required");
|
|
226
|
+
}
|
|
227
|
+
const symbol = requireNonEmptyString("symbol", options.symbol);
|
|
228
|
+
if (!/^[\x20-\x7e]+$/.test(symbol)) {
|
|
229
|
+
throw new RangeError("symbol must be ASCII printable");
|
|
230
|
+
}
|
|
231
|
+
const { decimals } = options;
|
|
232
|
+
if (!Number.isInteger(decimals) || decimals < 0 || decimals > 255) {
|
|
233
|
+
throw new RangeError("decimals must be a u8");
|
|
234
|
+
}
|
|
235
|
+
if (typeof options.initialSupply !== "bigint") {
|
|
236
|
+
throw new TypeError("initialSupply must be a bigint");
|
|
237
|
+
}
|
|
238
|
+
const initialSupply = requireU64("initialSupply", options.initialSupply);
|
|
239
|
+
const { supply } = options;
|
|
240
|
+
const supplyMode = SUPPLY_MODES[supply?.kind];
|
|
241
|
+
if (supplyMode === undefined) {
|
|
242
|
+
throw new TypeError("supply.kind must be mintable, fixed, or burnOnly");
|
|
243
|
+
}
|
|
244
|
+
if (supply.kind !== "mintable" && initialSupply === 0n) {
|
|
245
|
+
throw new RangeError(
|
|
246
|
+
"a fixed or burn-only supply must mint a nonzero initial supply",
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
const metadataMutable = options.metadataCapRecipient !== null;
|
|
250
|
+
|
|
251
|
+
return {
|
|
252
|
+
symbol,
|
|
253
|
+
name: requireNonEmptyString("name", options.name),
|
|
254
|
+
description: requireString("description", options.description),
|
|
255
|
+
iconUrl: requireString("iconUrl", options.iconUrl),
|
|
256
|
+
decimals,
|
|
257
|
+
initialSupply,
|
|
258
|
+
supplyRecipient: initialSupply
|
|
259
|
+
? recipient("supplyRecipient", options.supplyRecipient)
|
|
260
|
+
: normalizeSuiAddress("0x5ee1"),
|
|
261
|
+
supplyMode,
|
|
262
|
+
treasuryCapRecipient:
|
|
263
|
+
supply.kind === "mintable"
|
|
264
|
+
? recipient("supply.treasuryCapRecipient", supply.treasuryCapRecipient)
|
|
265
|
+
: normalizeSuiAddress("0x7ca9"),
|
|
266
|
+
metadataMutable,
|
|
267
|
+
metadataCapRecipient: metadataMutable
|
|
268
|
+
? recipient("metadataCapRecipient", options.metadataCapRecipient ?? "")
|
|
269
|
+
: normalizeSuiAddress("0x3e7a"),
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function recipient(name: string, address: string): string {
|
|
274
|
+
if (typeof address !== "string") {
|
|
275
|
+
throw new TypeError(`${name} must be a string`);
|
|
276
|
+
}
|
|
277
|
+
const normalized = normalizeSuiAddress(address);
|
|
278
|
+
if (!isValidSuiAddress(normalized) || BigInt(normalized) === 0n) {
|
|
279
|
+
throw new RangeError(`${name} must be a nonzero Sui address`);
|
|
280
|
+
}
|
|
281
|
+
return normalized;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function assertCoinTemplateWiring(
|
|
285
|
+
bytecode: Uint8Array,
|
|
286
|
+
identifiers: CoinTemplateIdentifiers,
|
|
287
|
+
): void {
|
|
288
|
+
const compiled = deserializeTemplate(LABEL, bytecode);
|
|
289
|
+
if (
|
|
290
|
+
!compiled.identifiers.includes(identifiers.moduleName) ||
|
|
291
|
+
!compiled.identifiers.includes(identifiers.witnessName)
|
|
292
|
+
) {
|
|
293
|
+
throw new TypeError("coin template identifiers were not patched");
|
|
294
|
+
}
|
|
295
|
+
const systemAddresses = new Set(
|
|
296
|
+
[normalizeSuiAddress("0x0"), ...COIN_PACKAGE_DEPENDENCIES].map((address) =>
|
|
297
|
+
normalizeSuiAddress(address).slice(2),
|
|
298
|
+
),
|
|
299
|
+
);
|
|
300
|
+
if (
|
|
301
|
+
!compiled.address_identifiers.every((address) =>
|
|
302
|
+
systemAddresses.has(address),
|
|
303
|
+
)
|
|
304
|
+
) {
|
|
305
|
+
throw new TypeError("coin template must link only 0x1 and 0x2");
|
|
306
|
+
}
|
|
307
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { TransactionObjectInput } from "@mysten/sui/transactions";
|
|
2
|
+
import { Transaction } from "@mysten/sui/transactions";
|
|
3
|
+
import {
|
|
4
|
+
normalizeStructTag,
|
|
5
|
+
normalizeSuiAddress,
|
|
6
|
+
SUI_FRAMEWORK_ADDRESS,
|
|
7
|
+
} from "@mysten/sui/utils";
|
|
8
|
+
|
|
9
|
+
import type { CoinTemplateOptions } from "./template.ts";
|
|
10
|
+
import {
|
|
11
|
+
buildCoinPackageBytecode,
|
|
12
|
+
COIN_PACKAGE_DEPENDENCIES,
|
|
13
|
+
} from "./template.ts";
|
|
14
|
+
|
|
15
|
+
export type CoinPublication = CoinTemplateOptions & {
|
|
16
|
+
/**
|
|
17
|
+
* Receives the package's `UpgradeCap`; null makes the package immutable in
|
|
18
|
+
* the same transaction, so nobody can ever change the coin's module.
|
|
19
|
+
*/
|
|
20
|
+
upgradeCapRecipient: string | null;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Publishes a standalone coin from the coin template (contracts ADR 0108).
|
|
25
|
+
* The initializer runs at publication and delivers the supply and the
|
|
26
|
+
* capabilities to the recipients `options` names; its `Currency` goes to the
|
|
27
|
+
* Coin Registry address, where anyone may share it with
|
|
28
|
+
* `coin_registry::finalize_registration` in a later transaction.
|
|
29
|
+
*/
|
|
30
|
+
export function publishCoin(options: CoinPublication): Transaction {
|
|
31
|
+
const tx = new Transaction();
|
|
32
|
+
const upgradeCap = tx.add(async (innerTx) => {
|
|
33
|
+
const module = await buildCoinPackageBytecode(options);
|
|
34
|
+
return innerTx.publish({
|
|
35
|
+
modules: [Array.from(module)],
|
|
36
|
+
dependencies: [...COIN_PACKAGE_DEPENDENCIES],
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
if (options.upgradeCapRecipient === null) {
|
|
40
|
+
tx.moveCall({
|
|
41
|
+
target: `${SUI_FRAMEWORK_ADDRESS}::package::make_immutable`,
|
|
42
|
+
arguments: [upgradeCap],
|
|
43
|
+
});
|
|
44
|
+
} else {
|
|
45
|
+
tx.transferObjects(
|
|
46
|
+
[upgradeCap],
|
|
47
|
+
normalizeSuiAddress(options.upgradeCapRecipient),
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
return tx;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Shares a published coin's pending Currency from the Coin Registry address. */
|
|
54
|
+
export function finalizeCoinRegistration(
|
|
55
|
+
tx: Transaction,
|
|
56
|
+
options: { coinType: string; currency: TransactionObjectInput },
|
|
57
|
+
): void {
|
|
58
|
+
tx.moveCall({
|
|
59
|
+
target: `${SUI_FRAMEWORK_ADDRESS}::coin_registry::finalize_registration`,
|
|
60
|
+
typeArguments: [normalizeStructTag(options.coinType)],
|
|
61
|
+
arguments: [tx.object("0xc"), tx.object(options.currency)],
|
|
62
|
+
});
|
|
63
|
+
}
|