@kaspacom/kcc20-tx-builder 0.5.0 → 0.6.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/CHANGELOG.md +6 -0
- package/README.md +2 -2
- package/RELEASING.md +19 -14
- package/artifacts/ArgentKCC20.reference.json +12428 -0
- package/artifacts/ArgentKCC20Wrapper.placeholder.json +12455 -0
- package/artifacts/KCC20.placeholder.json +1447 -1973
- package/artifacts/KCC20FeeTicket.placeholder.json +816 -1447
- package/artifacts/KCC20Orderbook.placeholder.json +1 -2
- package/artifacts/KCC20SnapshotBootstrap.placeholder.json +101 -100
- package/artifacts/KCC20SnapshotController.placeholder.json +101 -100
- package/artifacts/KCC20Vesting.placeholder.json +427 -429
- package/artifacts/KCC20Wrapper.placeholder.json +733 -734
- package/artifacts/kcc20-snapshot-bootstrap/KCC20SnapshotBootstrap.placeholder.json +101 -100
- package/artifacts/kcc20-snapshot-controller/KCC20SnapshotController.placeholder.json +101 -100
- package/artifacts/snapshot-standards.lock.json +6 -3
- package/artifacts/token-profiles.json +109 -0
- package/artifacts/token-profiles.sha256 +1 -0
- package/dist/action-source-resolver.d.ts.map +1 -1
- package/dist/action-source-resolver.js +11 -2
- package/dist/action-source-resolver.js.map +1 -1
- package/dist/artifacts.d.ts +10 -10
- package/dist/artifacts.d.ts.map +1 -1
- package/dist/artifacts.js +10 -10
- package/dist/artifacts.js.map +1 -1
- package/dist/cjs/action-source-resolver.js +11 -2
- package/dist/cjs/action-source-resolver.js.map +1 -1
- package/dist/cjs/artifacts.d.ts +10 -10
- package/dist/cjs/artifacts.js +10 -10
- package/dist/cjs/artifacts.js.map +1 -1
- package/dist/cjs/engine.d.ts +10 -0
- package/dist/cjs/engine.js +124 -77
- package/dist/cjs/engine.js.map +1 -1
- package/dist/cjs/index.d.ts +5 -0
- package/dist/cjs/index.js +5 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/profile-transfer.d.ts +60 -0
- package/dist/cjs/profile-transfer.js +248 -0
- package/dist/cjs/profile-transfer.js.map +1 -0
- package/dist/cjs/snapshot-signerless-transactions.js +2 -5
- package/dist/cjs/snapshot-signerless-transactions.js.map +1 -1
- package/dist/cjs/snapshot-signerless.js +5 -3
- package/dist/cjs/snapshot-signerless.js.map +1 -1
- package/dist/cjs/token-authorization.d.ts +42 -0
- package/dist/cjs/token-authorization.js +93 -0
- package/dist/cjs/token-authorization.js.map +1 -0
- package/dist/cjs/token-profiles.d.ts +82 -0
- package/dist/cjs/token-profiles.generated.d.ts +3 -0
- package/dist/cjs/token-profiles.generated.js +114 -0
- package/dist/cjs/token-profiles.generated.js.map +1 -0
- package/dist/cjs/token-profiles.js +257 -0
- package/dist/cjs/token-profiles.js.map +1 -0
- package/dist/cjs/transfer-payload.d.ts +9 -0
- package/dist/cjs/transfer-payload.js +37 -0
- package/dist/cjs/transfer-payload.js.map +1 -0
- package/dist/cjs/wrapper-operation.d.ts +1 -0
- package/dist/cjs/wrapper-operation.js +1 -0
- package/dist/cjs/wrapper-operation.js.map +1 -1
- package/dist/engine.d.ts +10 -0
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +125 -78
- package/dist/engine.js.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/profile-transfer.d.ts +61 -0
- package/dist/profile-transfer.d.ts.map +1 -0
- package/dist/profile-transfer.js +245 -0
- package/dist/profile-transfer.js.map +1 -0
- package/dist/snapshot-signerless-transactions.d.ts.map +1 -1
- package/dist/snapshot-signerless-transactions.js +2 -5
- package/dist/snapshot-signerless-transactions.js.map +1 -1
- package/dist/snapshot-signerless.d.ts.map +1 -1
- package/dist/snapshot-signerless.js +5 -3
- package/dist/snapshot-signerless.js.map +1 -1
- package/dist/token-authorization.d.ts +43 -0
- package/dist/token-authorization.d.ts.map +1 -0
- package/dist/token-authorization.js +88 -0
- package/dist/token-authorization.js.map +1 -0
- package/dist/token-profiles.d.ts +83 -0
- package/dist/token-profiles.d.ts.map +1 -0
- package/dist/token-profiles.generated.d.ts +4 -0
- package/dist/token-profiles.generated.d.ts.map +1 -0
- package/dist/token-profiles.generated.js +111 -0
- package/dist/token-profiles.generated.js.map +1 -0
- package/dist/token-profiles.js +245 -0
- package/dist/token-profiles.js.map +1 -0
- package/dist/transfer-payload.d.ts +10 -0
- package/dist/transfer-payload.d.ts.map +1 -0
- package/dist/transfer-payload.js +34 -0
- package/dist/transfer-payload.js.map +1 -0
- package/dist/wrapper-operation.d.ts +1 -0
- package/dist/wrapper-operation.d.ts.map +1 -1
- package/dist/wrapper-operation.js +1 -0
- package/dist/wrapper-operation.js.map +1 -1
- package/docs/COMPATIBILITY.json +24 -33
- package/docs/LAST_CALL.md +50 -0
- package/examples/README.md +3 -0
- package/examples/backend/cli.ts +2 -1
- package/examples/frontend/main.ts +2 -1
- package/examples/shared/build.ts +3 -0
- package/examples/shared/offline-profile.ts +27 -0
- package/examples/shared/recipe-fixtures.ts +3 -2
- package/examples/test/browser.ts +2 -2
- package/examples/test/build.test.ts +21 -8
- package/examples/test/sources.test.ts +3 -2
- package/package.json +2 -2
- package/src/action-source-resolver.ts +22 -4
- package/src/artifacts.ts +12 -10
- package/src/engine.ts +208 -105
- package/src/index.ts +7 -0
- package/src/profile-transfer.ts +425 -0
- package/src/snapshot-signerless-transactions.ts +7 -16
- package/src/snapshot-signerless.ts +5 -3
- package/src/token-authorization.ts +135 -0
- package/src/token-profiles.generated.ts +112 -0
- package/src/token-profiles.ts +456 -0
- package/src/transfer-payload.ts +45 -0
- package/src/wrapper-operation.ts +2 -0
package/dist/cjs/engine.js
CHANGED
|
@@ -2,7 +2,11 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createKcc20PsktBuilderEngine = createKcc20PsktBuilderEngine;
|
|
4
4
|
// @ts-nocheck
|
|
5
|
+
const token_authorization_js_1 = require("./token-authorization.js");
|
|
5
6
|
const sha256_1 = require("@noble/hashes/sha256");
|
|
7
|
+
const token_profiles_js_1 = require("./token-profiles.js");
|
|
8
|
+
const transfer_payload_js_1 = require("./transfer-payload.js");
|
|
9
|
+
const token_profiles_generated_js_1 = require("./token-profiles.generated.js");
|
|
6
10
|
const sale_common_js_1 = require("./sale-common.js");
|
|
7
11
|
const abi_js_1 = require("./abi.js");
|
|
8
12
|
const operations_js_1 = require("./operations.js");
|
|
@@ -105,6 +109,7 @@ function createKcc20PsktBuilderEngine(options) {
|
|
|
105
109
|
const WRAPPED_ARTIFACT_PATH = "KCC20Orderbook.placeholder.json";
|
|
106
110
|
const FEE_TICKET_ARTIFACT_PATH = "KCC20FeeTicket.placeholder.json";
|
|
107
111
|
const staticArtifactCache = new Map();
|
|
112
|
+
const tokenProfiles = (0, token_profiles_js_1.validateTokenProfileRegistry)(options.tokenProfileRegistry?.manifest ?? token_profiles_generated_js_1.BUNDLED_TOKEN_PROFILES, options.tokenProfileRegistry?.sha256 ?? token_profiles_generated_js_1.BUNDLED_TOKEN_PROFILE_DIGEST);
|
|
108
113
|
function readStaticArtifact(path) {
|
|
109
114
|
let cached = staticArtifactCache.get(path);
|
|
110
115
|
if (!cached) {
|
|
@@ -117,7 +122,16 @@ function createKcc20PsktBuilderEngine(options) {
|
|
|
117
122
|
? (artifact.artifact ?? artifact)
|
|
118
123
|
: artifact;
|
|
119
124
|
const normalized = (0, abi_js_1.normalizeSilverScriptArtifact)(artifactValue);
|
|
120
|
-
(
|
|
125
|
+
const profile = tokenProfiles.profiles.find((p) => p.artifactKey === path);
|
|
126
|
+
if (profile)
|
|
127
|
+
(0, token_profiles_js_1.authenticateTokenArtifact)(profile, artifactValue);
|
|
128
|
+
else {
|
|
129
|
+
const ownerProfile = tokenProfiles.profiles.find((p) => p.wrapper?.artifactKey === path);
|
|
130
|
+
if (ownerProfile)
|
|
131
|
+
(0, token_profiles_js_1.authenticateTokenWrapper)(ownerProfile, artifactValue);
|
|
132
|
+
else
|
|
133
|
+
(0, artifacts_js_1.assertKcc20ArtifactScriptHash)(path, normalized);
|
|
134
|
+
}
|
|
121
135
|
return normalized;
|
|
122
136
|
})
|
|
123
137
|
.catch((error) => {
|
|
@@ -135,15 +149,20 @@ function createKcc20PsktBuilderEngine(options) {
|
|
|
135
149
|
};
|
|
136
150
|
}
|
|
137
151
|
async function resolveKcc20ArtifactForState(state, address, network) {
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
152
|
+
for (const profile of tokenProfiles.profiles) {
|
|
153
|
+
const artifact = await readStaticArtifact(profile.artifactKey);
|
|
154
|
+
const script = (0, abi_js_1.buildKcc20ScriptForState)(artifact, state);
|
|
155
|
+
const candidateAddress = kaspaWasm
|
|
156
|
+
.addressFromScriptPublicKey(kaspaWasm.payToScriptHashScript(script), network)
|
|
157
|
+
.toString();
|
|
158
|
+
if (candidateAddress !== address)
|
|
159
|
+
continue;
|
|
160
|
+
(0, token_profiles_js_1.requireTokenCapability)(profile, "transfer");
|
|
161
|
+
if (!profile.ownerSchemes.includes(Number(state.ownerScheme ?? state.identifierType)))
|
|
162
|
+
throw new Error("owner scheme is unsupported by this token profile");
|
|
163
|
+
return { version: profile.id, profile, artifact, script };
|
|
145
164
|
}
|
|
146
|
-
|
|
165
|
+
throw new Error("KCC20 UTXO address does not match a bundled token profile");
|
|
147
166
|
}
|
|
148
167
|
function artifactEntrypointDispatchTag(artifact, entrypoint) {
|
|
149
168
|
try {
|
|
@@ -178,13 +197,14 @@ function createKcc20PsktBuilderEngine(options) {
|
|
|
178
197
|
},
|
|
179
198
|
];
|
|
180
199
|
}
|
|
181
|
-
async function readWrapperArtifacts() {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
200
|
+
async function readWrapperArtifacts(profile) {
|
|
201
|
+
if (!profile.wrapper)
|
|
202
|
+
return [];
|
|
203
|
+
return [{
|
|
204
|
+
artifact: await readStaticArtifact(profile.wrapper.artifactKey),
|
|
185
205
|
version: "standard-native-v1",
|
|
186
|
-
|
|
187
|
-
|
|
206
|
+
tokenProfileId: profile.id,
|
|
207
|
+
}];
|
|
188
208
|
}
|
|
189
209
|
function wrappedArtifactSupportsEntrypoint(info, name) {
|
|
190
210
|
return Array.isArray(info?.artifact?.abi)
|
|
@@ -544,7 +564,7 @@ function createKcc20PsktBuilderEngine(options) {
|
|
|
544
564
|
};
|
|
545
565
|
const kw = kaspaWasm;
|
|
546
566
|
const { CovenantBinding, Encoding, Hash, RpcClient, ScriptBuilder, Transaction, TransactionOutput, addressFromScriptPublicKey, payToAddressScript, payToScriptHashScript, } = kw;
|
|
547
|
-
const utilityScript = (0,
|
|
567
|
+
const utilityScript = (0, abi_js_1.buildKcc20ScriptForState)(kcc20Artifact, utilityState);
|
|
548
568
|
const rootAddress = requireKaspaAddress(rootUtxo.address);
|
|
549
569
|
const utilityAddress = requireKaspaAddress(utilityUtxo.address);
|
|
550
570
|
const rootArtifactInfo = selectFeeTicketArtifactForState(feeTicketArtifacts, rootState, rootAddress, network, "active FeeTicket root UTXO address");
|
|
@@ -1662,10 +1682,7 @@ function createKcc20PsktBuilderEngine(options) {
|
|
|
1662
1682
|
const feeTicketId = (0, sale_common_js_1.requireHex32)(params.feeTicketId || sale_common_js_1.ZERO_HASH, "fee ticket id");
|
|
1663
1683
|
const deployerOwner = (0, sale_common_js_1.requireHex32)(params.deployerOwner || request.owner?.kcc20Owner, "deployer owner");
|
|
1664
1684
|
const rootAmount = parseU64(params.wrappedRootAmount ?? "0", "wrappedRootAmount");
|
|
1665
|
-
const
|
|
1666
|
-
params.tokenDisplayScale ??
|
|
1667
|
-
sale_common_js_1.DEFAULT_KCC20_PRICE_SCALE, "priceScale");
|
|
1668
|
-
assertWrapperArtifactPriceScale(priceScale);
|
|
1685
|
+
const requestedPriceScale = params.priceScale ?? params.tokenDisplayScale;
|
|
1669
1686
|
const network = request.network || env.KASPA_NETWORK || "testnet-10";
|
|
1670
1687
|
const walletAddress = requireKaspaAddress(request.owner?.walletAddress);
|
|
1671
1688
|
const rpcUrl = env.KASPA_WRPC_URL || DEFAULT_WRPC_URL;
|
|
@@ -1674,7 +1691,19 @@ function createKcc20PsktBuilderEngine(options) {
|
|
|
1674
1691
|
DEFAULT_DEPLOY_TKAS, "KCC20_WRAPPER_DEPLOY_OUTPUT_TKAS");
|
|
1675
1692
|
const priorityFee = wrapperDeployPriorityFee(env.KCC20_WRAPPER_DEPLOY_PRIORITY_FEE_SOMPI);
|
|
1676
1693
|
const computeBudget = parsePositiveNumber(env.KCC20_WRAPPER_DEPLOY_COMPUTE_BUDGET || 600, "computeBudget");
|
|
1677
|
-
const
|
|
1694
|
+
const evidence = params.tokenUtxo;
|
|
1695
|
+
if (!evidence)
|
|
1696
|
+
throw new Error("authenticated token output is required before wrapper deployment");
|
|
1697
|
+
const sourceState = kcc20StateFromUtxo(evidence, request.owner);
|
|
1698
|
+
const sourceProfile = await resolveKcc20ArtifactForState(sourceState, requireKaspaAddress(evidence.address), network);
|
|
1699
|
+
(0, token_profiles_js_1.requireTokenCapability)(sourceProfile.profile, "wrap");
|
|
1700
|
+
if (!sourceProfile.profile.wrapper)
|
|
1701
|
+
throw new Error("token profile has no wrapper adapter");
|
|
1702
|
+
const priceScale = (0, token_profiles_js_1.resolveTokenProfilePriceScale)(sourceProfile.profile, requestedPriceScale === undefined
|
|
1703
|
+
? undefined
|
|
1704
|
+
: parsePositiveU64(requestedPriceScale, "priceScale"), sale_common_js_1.DEFAULT_KCC20_PRICE_SCALE);
|
|
1705
|
+
assertWrapperArtifactPriceScale(priceScale);
|
|
1706
|
+
const wrapperArtifact = await readStaticArtifact(sourceProfile.profile.wrapper.artifactKey);
|
|
1678
1707
|
const wrappedArtifacts = await readWrappedArtifacts();
|
|
1679
1708
|
const wrappedArtifact = wrappedArtifacts[0].artifact;
|
|
1680
1709
|
const wrapperState = {
|
|
@@ -1707,6 +1736,18 @@ function createKcc20PsktBuilderEngine(options) {
|
|
|
1707
1736
|
});
|
|
1708
1737
|
await rpc.connect();
|
|
1709
1738
|
try {
|
|
1739
|
+
const evidenceUtxos = await getUtxosByAddresses(rpc, [evidence.address]);
|
|
1740
|
+
const sourceEntry = findUtxoEntry(evidenceUtxos.entries, (0, sale_common_js_1.requireHex32)(evidence.txidHex, "token evidence txid"), parseVout(evidence.vout, "token evidence vout"));
|
|
1741
|
+
if (!sourceEntry)
|
|
1742
|
+
throw new Error("token evidence is spent or unavailable");
|
|
1743
|
+
requireMatchingCovenantId(sourceEntry, contractCanonicalTokenId, "wrapper token evidence");
|
|
1744
|
+
const sourceSpk = sourceEntry.scriptPublicKey ??
|
|
1745
|
+
sourceEntry.entry?.scriptPublicKey ??
|
|
1746
|
+
sourceEntry.utxoEntry?.scriptPublicKey;
|
|
1747
|
+
if (!sourceSpk ||
|
|
1748
|
+
kw.addressFromScriptPublicKey(sourceSpk, network)?.toString() !==
|
|
1749
|
+
evidence.address)
|
|
1750
|
+
throw new Error("token evidence script does not match RPC");
|
|
1710
1751
|
const utxos = await getUtxosByAddresses(rpc, [walletAddress]);
|
|
1711
1752
|
const fundingEntry = (0, sale_common_js_1.selectFundingEntry)(utxos.entries, deploySompi * 2n + priorityFee + 10000000n);
|
|
1712
1753
|
const fundingChangeOutputIndex = 2;
|
|
@@ -1787,6 +1828,9 @@ function createKcc20PsktBuilderEngine(options) {
|
|
|
1787
1828
|
submitTransactionSupported: true,
|
|
1788
1829
|
metadata: {
|
|
1789
1830
|
builderKey: "kcc20wrapper.deploy-market",
|
|
1831
|
+
tokenProfileId: sourceProfile.profile.id,
|
|
1832
|
+
tokenProfileRegistryHash: options.tokenProfileRegistry?.sha256 ??
|
|
1833
|
+
token_profiles_generated_js_1.BUNDLED_TOKEN_PROFILE_DIGEST,
|
|
1790
1834
|
contract: "KCC20Wrapper",
|
|
1791
1835
|
network,
|
|
1792
1836
|
walletAddress,
|
|
@@ -1866,10 +1910,7 @@ function createKcc20PsktBuilderEngine(options) {
|
|
|
1866
1910
|
sale_common_js_1.DEFAULT_TOKEN_OUTPUT_SOMPI.toString(), "tokenOutputSompi");
|
|
1867
1911
|
const priorityFee = parseU64(env.KCC20_WRAP_PRIORITY_FEE_SOMPI || DEFAULT_PRIORITY_FEE.toString(), "priorityFee");
|
|
1868
1912
|
const computeBudget = parsePositiveNumber(env.KCC20_WRAP_COMPUTE_BUDGET || 700, "computeBudget");
|
|
1869
|
-
const
|
|
1870
|
-
readWrapperArtifacts(),
|
|
1871
|
-
readWrappedArtifacts(),
|
|
1872
|
-
]);
|
|
1913
|
+
const wrappedArtifacts = await readWrappedArtifacts();
|
|
1873
1914
|
const holderState = kcc20StateFromUtxo(holderUtxo, request.owner);
|
|
1874
1915
|
if (holderState.identifierType !== 0) {
|
|
1875
1916
|
throw new Error("wrap requires pubkey-owned KCC20 holder UTXO");
|
|
@@ -1884,6 +1925,8 @@ function createKcc20PsktBuilderEngine(options) {
|
|
|
1884
1925
|
}
|
|
1885
1926
|
const kcc20ArtifactInfo = await resolveKcc20ArtifactForState(holderState, requireKaspaAddress(holderUtxo.address), network);
|
|
1886
1927
|
const kcc20Artifact = kcc20ArtifactInfo.artifact;
|
|
1928
|
+
(0, token_profiles_js_1.requireTokenCapability)(kcc20ArtifactInfo.profile, "wrap");
|
|
1929
|
+
const wrapperArtifacts = await readWrapperArtifacts(kcc20ArtifactInfo.profile);
|
|
1887
1930
|
const remaining = holderState.amount - tokenAmount;
|
|
1888
1931
|
const priceScale = parsePositiveU64(wrapperUtxo.state?.priceScale ??
|
|
1889
1932
|
wrapperUtxo.state?.tokenDisplayScale ??
|
|
@@ -1910,7 +1953,7 @@ function createKcc20PsktBuilderEngine(options) {
|
|
|
1910
1953
|
const { CovenantBinding, Encoding, Hash, RpcClient, ScriptBuilder, Transaction, TransactionOutput, payToAddressScript, payToScriptHashScript, } = kw;
|
|
1911
1954
|
const wrapperArtifactInfo = selectWrapperArtifactForUtxo({
|
|
1912
1955
|
kw,
|
|
1913
|
-
artifacts: wrapperArtifacts,
|
|
1956
|
+
artifacts: wrapperArtifacts.filter((info) => info.tokenProfileId === kcc20ArtifactInfo.profile.id),
|
|
1914
1957
|
state: wrapperState,
|
|
1915
1958
|
utxo: wrapperUtxo,
|
|
1916
1959
|
network,
|
|
@@ -1923,7 +1966,7 @@ function createKcc20PsktBuilderEngine(options) {
|
|
|
1923
1966
|
const wrapperArtifact = wrapperArtifactInfo.artifact;
|
|
1924
1967
|
const wrappedArtifact = wrappedArtifactInfo.artifact;
|
|
1925
1968
|
const wrapperScript = wrapperArtifactInfo.script;
|
|
1926
|
-
const holderScript = (0,
|
|
1969
|
+
const holderScript = (0, abi_js_1.buildKcc20ScriptForState)(kcc20Artifact, holderState);
|
|
1927
1970
|
const wrapperAddress = requireKaspaAddress(wrapperUtxo.address);
|
|
1928
1971
|
const holderAddress = requireKaspaAddress(holderUtxo.address);
|
|
1929
1972
|
assertScriptAddress(kw, holderScript, holderAddress, network, "KCC20 holder UTXO address");
|
|
@@ -2136,10 +2179,7 @@ function createKcc20PsktBuilderEngine(options) {
|
|
|
2136
2179
|
sale_common_js_1.DEFAULT_TOKEN_OUTPUT_SOMPI.toString(), "tokenOutputSompi");
|
|
2137
2180
|
const priorityFee = parseU64(env.KCC20_UNWRAP_PRIORITY_FEE_SOMPI || DEFAULT_PRIORITY_FEE.toString(), "priorityFee");
|
|
2138
2181
|
const computeBudget = parsePositiveNumber(env.KCC20_UNWRAP_COMPUTE_BUDGET || 700, "computeBudget");
|
|
2139
|
-
const
|
|
2140
|
-
readWrapperArtifacts(),
|
|
2141
|
-
readWrappedArtifacts(),
|
|
2142
|
-
]);
|
|
2182
|
+
const wrappedArtifacts = await readWrappedArtifacts();
|
|
2143
2183
|
const reserveState = kcc20StateFromUtxo(reserveUtxo, request.owner);
|
|
2144
2184
|
if (reserveState.ownerScheme !== 4 || reserveState.isMintAuthority) {
|
|
2145
2185
|
throw new Error("KCC20 reserve UTXO must be covenant-owned holder state");
|
|
@@ -2149,6 +2189,8 @@ function createKcc20PsktBuilderEngine(options) {
|
|
|
2149
2189
|
}
|
|
2150
2190
|
const kcc20ArtifactInfo = await resolveKcc20ArtifactForState(reserveState, requireKaspaAddress(reserveUtxo.address), network);
|
|
2151
2191
|
const kcc20Artifact = kcc20ArtifactInfo.artifact;
|
|
2192
|
+
(0, token_profiles_js_1.requireTokenCapability)(kcc20ArtifactInfo.profile, "unwrap");
|
|
2193
|
+
const wrapperArtifacts = await readWrapperArtifacts(kcc20ArtifactInfo.profile);
|
|
2152
2194
|
const wrappedState = kcc20V3WrappedStateFromUtxo(wrappedUtxo, canonicalTokenId, request.owner);
|
|
2153
2195
|
if ((0, sale_common_js_1.bytesToHex)(wrappedState.ownerIdentifier) !== recipientOwner) {
|
|
2154
2196
|
throw new Error("KCC20 orderbook holder UTXO is not owned by authenticated wallet");
|
|
@@ -2192,7 +2234,7 @@ function createKcc20PsktBuilderEngine(options) {
|
|
|
2192
2234
|
const { CovenantBinding, Encoding, Hash, RpcClient, ScriptBuilder, Transaction, TransactionOutput, payToAddressScript, payToScriptHashScript, } = kw;
|
|
2193
2235
|
const wrapperArtifactInfo = selectWrapperArtifactForUtxo({
|
|
2194
2236
|
kw,
|
|
2195
|
-
artifacts: wrapperArtifacts,
|
|
2237
|
+
artifacts: wrapperArtifacts.filter((info) => info.tokenProfileId === kcc20ArtifactInfo.profile.id),
|
|
2196
2238
|
state: wrapperState,
|
|
2197
2239
|
utxo: wrapperUtxo,
|
|
2198
2240
|
network,
|
|
@@ -2214,7 +2256,7 @@ function createKcc20PsktBuilderEngine(options) {
|
|
|
2214
2256
|
const wrapperScript = wrapperArtifactInfo.script;
|
|
2215
2257
|
const wrappedScript = wrappedArtifactInfo.script;
|
|
2216
2258
|
const refundAware = wrappedArtifactRefundsHolderDeposits(wrappedArtifactInfo);
|
|
2217
|
-
const reserveScript = (0,
|
|
2259
|
+
const reserveScript = (0, abi_js_1.buildKcc20ScriptForState)(kcc20Artifact, reserveState);
|
|
2218
2260
|
const wrapperAddress = wrapperArtifactInfo.address;
|
|
2219
2261
|
const wrappedAddress = wrappedArtifactInfo.address;
|
|
2220
2262
|
const reserveAddress = requireKaspaAddress(reserveUtxo.address);
|
|
@@ -5668,6 +5710,7 @@ function createKcc20PsktBuilderEngine(options) {
|
|
|
5668
5710
|
extensionCommitment: (0, abi_js_1.mintExtensionCommitment)(extension),
|
|
5669
5711
|
};
|
|
5670
5712
|
const resolvedArtifact = await resolveKcc20ArtifactForState(inputState, minterAddress, network);
|
|
5713
|
+
(0, token_profiles_js_1.requireTokenCapability)(resolvedArtifact.profile, "mint");
|
|
5671
5714
|
const artifact = resolvedArtifact.artifact;
|
|
5672
5715
|
const recipientState = {
|
|
5673
5716
|
amount: mintAmount,
|
|
@@ -5957,6 +6000,7 @@ function createKcc20PsktBuilderEngine(options) {
|
|
|
5957
6000
|
extensionCommitment: (0, abi_js_1.mintExtensionCommitment)(nextExtension),
|
|
5958
6001
|
};
|
|
5959
6002
|
const resolvedArtifact = await resolveKcc20ArtifactForState(inputState, minterAddress, network);
|
|
6003
|
+
(0, token_profiles_js_1.requireTokenCapability)(resolvedArtifact.profile, "mint");
|
|
5960
6004
|
(0, abi_js_1.dispatchTagFor)(resolvedArtifact.artifact, "set_public_mint_active");
|
|
5961
6005
|
const minterTxid = (0, sale_common_js_1.requireHex32)(activeMinterUtxo.txidHex, "minter txid");
|
|
5962
6006
|
const minterVout = parseVout(activeMinterUtxo.vout, "minter vout");
|
|
@@ -6180,6 +6224,10 @@ function createKcc20PsktBuilderEngine(options) {
|
|
|
6180
6224
|
if (resolvedArtifacts.some((candidate) => candidate.version !== resolvedArtifacts[0].version)) {
|
|
6181
6225
|
throw new Error("consolidation requires holder UTXOs from one artifact");
|
|
6182
6226
|
}
|
|
6227
|
+
const profile = resolvedArtifacts[0].profile;
|
|
6228
|
+
if (holderUtxos.length > profile.maxTokenInputs) {
|
|
6229
|
+
throw new Error("consolidation exceeds the token profile input bound");
|
|
6230
|
+
}
|
|
6183
6231
|
const artifact = resolvedArtifacts[0].artifact;
|
|
6184
6232
|
for (const peerState of states.slice(1)) {
|
|
6185
6233
|
assertKcc20MergeableStates(primaryState, peerState, owner);
|
|
@@ -6483,12 +6531,6 @@ function createKcc20PsktBuilderEngine(options) {
|
|
|
6483
6531
|
if (inputState.isMintAuthority || inputState.amount <= 0n) {
|
|
6484
6532
|
throw new Error("KCC20 transfer requires a holder UTXO");
|
|
6485
6533
|
}
|
|
6486
|
-
if (inputState.ownerScheme !== 0) {
|
|
6487
|
-
throw new Error("KCC20 transfer requires a Schnorr P2PK holder UTXO");
|
|
6488
|
-
}
|
|
6489
|
-
if ((0, sale_common_js_1.bytesToHex)(inputState.ownerIdentifier) !== owner) {
|
|
6490
|
-
throw new Error("KCC20 transfer requires wallet to own the active holder UTXO");
|
|
6491
|
-
}
|
|
6492
6534
|
if (transferAmount > inputState.amount) {
|
|
6493
6535
|
throw new Error("tokenAmount exceeds active holder balance");
|
|
6494
6536
|
}
|
|
@@ -6497,6 +6539,21 @@ function createKcc20PsktBuilderEngine(options) {
|
|
|
6497
6539
|
const tokenAddress = requireKaspaAddress(activeHolderUtxo.address);
|
|
6498
6540
|
const resolvedArtifact = await resolveKcc20ArtifactForState(inputState, tokenAddress, network);
|
|
6499
6541
|
const artifact = resolvedArtifact.artifact;
|
|
6542
|
+
if (params.mode && params.mode !== "owner")
|
|
6543
|
+
throw new Error("borrowed receive requires the explicit borrow transaction builder");
|
|
6544
|
+
const authorization = (0, token_authorization_js_1.planTokenOwnerWitness)({
|
|
6545
|
+
profile: resolvedArtifact.profile,
|
|
6546
|
+
owner: (0, sale_common_js_1.bytesToHex)(inputState.ownerIdentifier),
|
|
6547
|
+
ownerScheme: inputState.ownerScheme,
|
|
6548
|
+
publicKey: request.owner?.publicKey ?? request.owner?.kcc20Owner,
|
|
6549
|
+
capabilities: options.walletSigningCapabilities ?? {
|
|
6550
|
+
schnorr: true,
|
|
6551
|
+
ecdsa: false,
|
|
6552
|
+
},
|
|
6553
|
+
role: "leader",
|
|
6554
|
+
});
|
|
6555
|
+
if (!resolvedArtifact.profile.ownerSchemes.includes(recipientOwnerScheme))
|
|
6556
|
+
throw new Error("recipient owner scheme is unsupported by the token profile");
|
|
6500
6557
|
const recipientState = {
|
|
6501
6558
|
...inputState,
|
|
6502
6559
|
owner: (0, sale_common_js_1.hexToBytes)(recipientOwner),
|
|
@@ -6528,8 +6585,11 @@ function createKcc20PsktBuilderEngine(options) {
|
|
|
6528
6585
|
throw new Error(`active holder UTXO ${tokenTxid}:${tokenVout} not found`);
|
|
6529
6586
|
}
|
|
6530
6587
|
const rpcScript = tokenEntry.scriptPublicKey ??
|
|
6531
|
-
tokenEntry.entry?.scriptPublicKey ??
|
|
6532
|
-
|
|
6588
|
+
tokenEntry.entry?.scriptPublicKey ??
|
|
6589
|
+
tokenEntry.utxoEntry?.scriptPublicKey;
|
|
6590
|
+
if (!rpcScript ||
|
|
6591
|
+
kw.addressFromScriptPublicKey(rpcScript, network)?.toString() !==
|
|
6592
|
+
tokenAddress) {
|
|
6533
6593
|
throw new Error("active holder RPC script does not match rebuilt covenant state");
|
|
6534
6594
|
}
|
|
6535
6595
|
if (activeHolderUtxo.amountSompi != null &&
|
|
@@ -6538,7 +6598,7 @@ function createKcc20PsktBuilderEngine(options) {
|
|
|
6538
6598
|
}
|
|
6539
6599
|
const spendCovenantId = params.activeHolderNativeCovenantId
|
|
6540
6600
|
? requireMatchingCovenantId(tokenEntry, covenantId, "active holder")
|
|
6541
|
-
: covenantIdFromUtxoEntry(tokenEntry) ?? covenantId;
|
|
6601
|
+
: (covenantIdFromUtxoEntry(tokenEntry) ?? covenantId);
|
|
6542
6602
|
let outputSompi = 0n;
|
|
6543
6603
|
const recipientOutputIndex = 0;
|
|
6544
6604
|
const outputs = [
|
|
@@ -6590,9 +6650,9 @@ function createKcc20PsktBuilderEngine(options) {
|
|
|
6590
6650
|
outputs,
|
|
6591
6651
|
subnetworkId: sale_common_js_1.SUBNETWORK_ID_NATIVE,
|
|
6592
6652
|
gas: 0n,
|
|
6593
|
-
payload:
|
|
6653
|
+
payload: (0, transfer_payload_js_1.buildAuthenticatedKcc20TransferPayload)({
|
|
6594
6654
|
covenantId: spendCovenantId,
|
|
6595
|
-
|
|
6655
|
+
fromOwnerIdentifier: (0, sale_common_js_1.bytesToHex)(inputState.ownerIdentifier),
|
|
6596
6656
|
recipientOwner,
|
|
6597
6657
|
recipientOwnerScheme,
|
|
6598
6658
|
tokenAmount: transferAmount,
|
|
@@ -6605,9 +6665,10 @@ function createKcc20PsktBuilderEngine(options) {
|
|
|
6605
6665
|
inputIndex: 0,
|
|
6606
6666
|
scriptHex: (0, sale_common_js_1.bytesToHex)(tokenScript),
|
|
6607
6667
|
signType: 1,
|
|
6668
|
+
signatureAlgorithm: authorization.signatureAlgorithm,
|
|
6608
6669
|
signatureScript: {
|
|
6609
6670
|
mode: "ordered-args",
|
|
6610
|
-
args: kcc20TransferOrderedArgs(artifact, changeState ? [recipientState, changeState] : [recipientState]),
|
|
6671
|
+
args: kcc20TransferOrderedArgs(artifact, changeState ? [recipientState, changeState] : [recipientState], authorization.argument),
|
|
6611
6672
|
},
|
|
6612
6673
|
},
|
|
6613
6674
|
];
|
|
@@ -6623,6 +6684,9 @@ function createKcc20PsktBuilderEngine(options) {
|
|
|
6623
6684
|
scripts,
|
|
6624
6685
|
submitTransactionSupported: true,
|
|
6625
6686
|
metadata: {
|
|
6687
|
+
tokenProfileId: resolvedArtifact.profile.id,
|
|
6688
|
+
tokenProfileRegistryHash: options.tokenProfileRegistry?.sha256 ??
|
|
6689
|
+
token_profiles_generated_js_1.BUNDLED_TOKEN_PROFILE_DIGEST,
|
|
6626
6690
|
builderKey: "kcc20.transfer",
|
|
6627
6691
|
operation: "transfer-token",
|
|
6628
6692
|
action: "transfer",
|
|
@@ -7617,34 +7681,6 @@ function createKcc20PsktBuilderEngine(options) {
|
|
|
7617
7681
|
},
|
|
7618
7682
|
}));
|
|
7619
7683
|
}
|
|
7620
|
-
function buildTransferPayload(fields) {
|
|
7621
|
-
return new TextEncoder().encode(JSON.stringify({
|
|
7622
|
-
tn12: {
|
|
7623
|
-
v: 1,
|
|
7624
|
-
tmpl: "KCC20",
|
|
7625
|
-
op: "transfer",
|
|
7626
|
-
args: [
|
|
7627
|
-
{ name: "covenantId", type: "byte[32]", value: fields.covenantId },
|
|
7628
|
-
{ name: "fromOwner", type: "byte[32]", value: fields.fromOwner },
|
|
7629
|
-
{
|
|
7630
|
-
name: "recipientOwner",
|
|
7631
|
-
type: "byte[32]",
|
|
7632
|
-
value: fields.recipientOwner,
|
|
7633
|
-
},
|
|
7634
|
-
{
|
|
7635
|
-
name: "recipientOwnerScheme",
|
|
7636
|
-
type: "u64",
|
|
7637
|
-
value: String(fields.recipientOwnerScheme),
|
|
7638
|
-
},
|
|
7639
|
-
{
|
|
7640
|
-
name: "tokenAmount",
|
|
7641
|
-
type: "u64",
|
|
7642
|
-
value: fields.tokenAmount.toString(),
|
|
7643
|
-
},
|
|
7644
|
-
],
|
|
7645
|
-
},
|
|
7646
|
-
}));
|
|
7647
|
-
}
|
|
7648
7684
|
function tokenOutput(kw, artifact, state, sompi, covenantId, authorizingInput) {
|
|
7649
7685
|
return new kw.TransactionOutput(sompi, kw.payToScriptHashScript((0, abi_js_1.buildKcc20ScriptForState)(artifact, state)), new kw.CovenantBinding(authorizingInput, new kw.Hash(covenantId)));
|
|
7650
7686
|
}
|
|
@@ -8940,18 +8976,29 @@ function createKcc20PsktBuilderEngine(options) {
|
|
|
8940
8976
|
values.push({ type: "signature" }, i64TemplateArg(active ? 1 : 0), i64TemplateArg(minterOutputIndex), dataTemplateArg((0, abi_js_1.dispatchTagFor)(artifact, "set_public_mint_active")));
|
|
8941
8977
|
return values;
|
|
8942
8978
|
}
|
|
8943
|
-
function
|
|
8979
|
+
function profileForArtifact(artifact) {
|
|
8980
|
+
const parts = templateParts(artifact);
|
|
8981
|
+
const hash = (0, sale_common_js_1.bytesToHex)((0, abi_js_1.templateHash)(parts.prefix, parts.suffix));
|
|
8982
|
+
const profile = tokenProfiles.profiles.find((p) => p.templateHash === hash);
|
|
8983
|
+
if (!profile)
|
|
8984
|
+
throw new Error("token artifact has no bundled profile");
|
|
8985
|
+
return profile;
|
|
8986
|
+
}
|
|
8987
|
+
function kcc20TransferOrderedArgs(artifact, nextStates, witness) {
|
|
8988
|
+
const profile = profileForArtifact(artifact);
|
|
8989
|
+
if (nextStates.length > profile.maxTokenOutputs)
|
|
8990
|
+
throw new Error("transfer exceeds profile output bound");
|
|
8944
8991
|
const fields = (0, abi_js_1.encodeKcc20StateRecordArrays)(nextStates).map(dataTemplateArg);
|
|
8945
8992
|
return [
|
|
8946
8993
|
...fields,
|
|
8947
|
-
{ type: "signature", prefixHex: "00" },
|
|
8948
|
-
dataTemplateArg((0, abi_js_1.dispatchTagFor)(artifact,
|
|
8994
|
+
witness ?? { type: "signature", prefixHex: "00" },
|
|
8995
|
+
dataTemplateArg((0, abi_js_1.dispatchTagFor)(artifact, profileForArtifact(artifact).transferEntrypoint)),
|
|
8949
8996
|
];
|
|
8950
8997
|
}
|
|
8951
8998
|
function kcc20TransferDelegatorOrderedArgs(artifact) {
|
|
8952
8999
|
return [
|
|
8953
9000
|
{ type: "signature" },
|
|
8954
|
-
dataTemplateArg((0, abi_js_1.dispatchTagFor)(artifact,
|
|
9001
|
+
dataTemplateArg((0, abi_js_1.dispatchTagFor)(artifact, profileForArtifact(artifact).delegatorEntrypoint)),
|
|
8955
9002
|
];
|
|
8956
9003
|
}
|
|
8957
9004
|
function kcc20BurnOrderedArgs(artifact, nextStates, burnAmount) {
|