@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 CHANGED
@@ -1,3 +1,9 @@
1
- # Temporary Holding Version
1
+ # @interest-protocol/blast-coin-sdk
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
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.
@@ -0,0 +1,3 @@
1
+ export * from "./template.ts";
2
+ export * from "./transactions.ts";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -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,3 @@
1
+ export * from "./template.js";
2
+ export * from "./transactions.js";
3
+ //# sourceMappingURL=index.js.map
@@ -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"}
@@ -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.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
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
@@ -0,0 +1,2 @@
1
+ export * from "./template.ts";
2
+ export * from "./transactions.ts";
@@ -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
+ }