@kronsdk/kron-sdk 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/README.md +11 -9
- package/dist/index.d.ts +10 -1
- package/dist/index.js +62 -40
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,16 +4,18 @@
|
|
|
4
4
|
— a bonding-curve launchpad + AMM DEX — from any JS/TS environment.** Browser or Node. No custody, ever:
|
|
5
5
|
this package only *builds* transactions; a wallet (yours, or your user's) signs them.
|
|
6
6
|
|
|
7
|
-
> **Status: v0.
|
|
7
|
+
> **Status: v0.6.0, testnet (TN10).** Read paths and the covenant builders are proven byte-identical to
|
|
8
8
|
> KRON's own production code (see "Verification" below). Wallet signing is a documented interface plus a
|
|
9
9
|
> generic reference implementation — see [`docs/WALLETS.md`](docs/WALLETS.md) for the contract and how to
|
|
10
10
|
> adapt it to a specific wallet's injected provider.
|
|
11
11
|
>
|
|
12
|
-
> **⚠️ Upgrade from < 0.
|
|
12
|
+
> **⚠️ Upgrade from < 0.6.0.** Every earlier release built **version-0** transactions, which cannot carry
|
|
13
13
|
> the covenant bindings Kaspa's covenant layer (KIP-20) requires on output — every assembled spend was
|
|
14
|
-
> rejected on-chain with `script ran, but verification failed`.
|
|
15
|
-
>
|
|
16
|
-
>
|
|
14
|
+
> rejected on-chain with `script ran, but verification failed`. 0.5.0 fixed `assembleNativeTx` (v1 txs +
|
|
15
|
+
> compute budgets) and the kcc20 builders; 0.6.0 finishes the job for the curve, pool/LP, and vesting
|
|
16
|
+
> builders (buy/sell/graduate, swap, add/removeLiquidity, bindLp, claim) — they now attach the required
|
|
17
|
+
> `CovOutput.binding` automatically. See the [CHANGELOG](CHANGELOG.md) for the migration notes if you
|
|
18
|
+
> assembled transactions by hand instead of via `spend.assembleNativeTx`.
|
|
17
19
|
|
|
18
20
|
## Why this exists
|
|
19
21
|
|
|
@@ -40,12 +42,12 @@ ESM only (`"type": "module"`) in v1 — see [Design notes](#design-notes) for wh
|
|
|
40
42
|
|
|
41
43
|
```bash
|
|
42
44
|
npm install @kronsdk/kron-sdk@latest # newest
|
|
43
|
-
npm install @kronsdk/kron-sdk@0.
|
|
45
|
+
npm install @kronsdk/kron-sdk@0.6.0 # or pin an exact version for reproducible builds
|
|
44
46
|
```
|
|
45
47
|
|
|
46
|
-
The package follows semver. **0.
|
|
47
|
-
the warning above. The token-list client (`client.RegistryClient.tokenlist()`) and
|
|
48
|
-
(`verify.verifyTokenListEntry`) landed in **0.2.0** — see [Discover & verify tokens](#discover--verify-tokens-token-list).
|
|
48
|
+
The package follows semver. **0.6.0 is a required upgrade for anyone building curve/pool/LP/vesting
|
|
49
|
+
transactions** — see the warning above. The token-list client (`client.RegistryClient.tokenlist()`) and
|
|
50
|
+
on-chain verifier (`verify.verifyTokenListEntry`) landed in **0.2.0** — see [Discover & verify tokens](#discover--verify-tokens-token-list).
|
|
49
51
|
|
|
50
52
|
## Quickstart — quote a curve buy (Node)
|
|
51
53
|
|
package/dist/index.d.ts
CHANGED
|
@@ -814,14 +814,23 @@ type VestUtxo = {
|
|
|
814
814
|
* Partial claim: release `release` (0 < release < remaining) to the creator's presence, re-lock the rest under
|
|
815
815
|
* V. inputs [vesting(0), lockedToken(1)]; outputs [vesting cont(0), relock(1, A/V-owned), recipient(2, A/creator)].
|
|
816
816
|
* The flow must set tx.lockTime = current DAA score (consensus blocks the tx until then; the covenant reads it).
|
|
817
|
+
*
|
|
818
|
+
* Pass `opts.tokenCovid` (the vested token's covenant id, hex — `covenantId` from the indexer) so the relock +
|
|
819
|
+
* recipient outputs carry the KIP-20 covenant binding the chain requires; without it the assembled tx fails
|
|
820
|
+
* on-chain. The vesting-continuation output is always bound to `vestingCovid` (already a required param).
|
|
817
821
|
*/
|
|
818
822
|
declare function buildVestingClaim(k: K, vestTpl: VestingTemplate, tokenTpl: Kcc20Template, vestingUtxo: VestUtxo, lockedToken: VestUtxo, vestingCovid: Uint8Array, creatorPubkey: Uint8Array, claimed: bigint, release: bigint, opts?: {
|
|
819
823
|
tokenDust?: bigint;
|
|
824
|
+
tokenCovid?: string;
|
|
820
825
|
}): CovenantSpend;
|
|
821
826
|
/** Final claim: once fully vested, pay ALL remaining to the creator and continue V with claimed=total (husk).
|
|
822
|
-
* inputs [vesting(0), lockedToken(1)]; outputs [vesting cont(0), recipient(1, A/creator)].
|
|
827
|
+
* inputs [vesting(0), lockedToken(1)]; outputs [vesting cont(0), recipient(1, A/creator)].
|
|
828
|
+
*
|
|
829
|
+
* Pass `opts.tokenCovid` (the vested token's covenant id, hex) so the recipient output carries the KIP-20
|
|
830
|
+
* covenant binding the chain requires; without it the assembled tx fails on-chain. */
|
|
823
831
|
declare function buildVestingClaimFinal(k: K, vestTpl: VestingTemplate, tokenTpl: Kcc20Template, vestingUtxo: VestUtxo, lockedToken: VestUtxo, vestingCovid: Uint8Array, creatorPubkey: Uint8Array, claimed: bigint, opts?: {
|
|
824
832
|
tokenDust?: bigint;
|
|
833
|
+
tokenCovid?: string;
|
|
825
834
|
}): CovenantSpend;
|
|
826
835
|
|
|
827
836
|
declare const vestingTx_VEST_SELECTOR: typeof VEST_SELECTOR;
|
package/dist/index.js
CHANGED
|
@@ -578,6 +578,9 @@ function buildAddLiquidity(k, tpl, tokenTpl, utxo, lpInventory, poolCovid, lpDep
|
|
|
578
578
|
if (lpDepositToken.state.amount !== q.dToken) throw new Error("LP deposit token UTXO must equal dToken exactly (split first)");
|
|
579
579
|
const dust = opts.tokenDust ?? 1000n;
|
|
580
580
|
const { kasReserve, tokenReserve, tokenCovid, lpCovid } = utxo.state;
|
|
581
|
+
const poolCovidHex = hexOf(poolCovid);
|
|
582
|
+
const tokenCovidHex = hexOf(tokenCovid);
|
|
583
|
+
const lpCovidHex = hexOf(lpCovid);
|
|
581
584
|
const poolTokenOut = covenantIdOwned(poolCovid, q.newToken, false);
|
|
582
585
|
const poolLpOut = covenantIdOwned(poolCovid, lpInventory.amount - q.dShares, false);
|
|
583
586
|
const lpSharesOut = addressPresenceOwned(lpPubkey, q.dShares);
|
|
@@ -597,17 +600,20 @@ function buildAddLiquidity(k, tpl, tokenTpl, utxo, lpInventory, poolCovid, lpDep
|
|
|
597
600
|
{ transactionId: lpInventory.transactionId, index: lpInventory.index, value: lpInventory.value, scriptPublicKey: kcc20Spk(k, poolLpInvRedeem), signatureScript: transferSigScript(k, poolLpInvRedeem, lStates, lWitnesses), redeem: poolLpInvRedeem, role: "poolLpInventory" }
|
|
598
601
|
];
|
|
599
602
|
const outputs = [
|
|
600
|
-
{ value: q.newKas * SCALE, scriptPublicKey: poolCpSpk(k, newRedeem), role: "pool" },
|
|
601
|
-
{ value: dust, scriptPublicKey: kcc20Spk(k, materializeKcc20Script(tokenTpl, poolTokenOut)), role: "poolToken" },
|
|
602
|
-
{ value: dust, scriptPublicKey: kcc20Spk(k, materializeKcc20Script(tokenTpl, poolLpOut)), role: "poolLpInventory" },
|
|
603
|
-
{ value: dust, scriptPublicKey: kcc20Spk(k, materializeKcc20Script(tokenTpl, lpSharesOut)), role: "lpShares" }
|
|
603
|
+
{ value: q.newKas * SCALE, scriptPublicKey: poolCpSpk(k, newRedeem), role: "pool", binding: { covid: poolCovidHex, authorizingInput: 0 } },
|
|
604
|
+
{ value: dust, scriptPublicKey: kcc20Spk(k, materializeKcc20Script(tokenTpl, poolTokenOut)), role: "poolToken", binding: { covid: tokenCovidHex, authorizingInput: 2 } },
|
|
605
|
+
{ value: dust, scriptPublicKey: kcc20Spk(k, materializeKcc20Script(tokenTpl, poolLpOut)), role: "poolLpInventory", binding: { covid: lpCovidHex, authorizingInput: 3 } },
|
|
606
|
+
{ value: dust, scriptPublicKey: kcc20Spk(k, materializeKcc20Script(tokenTpl, lpSharesOut)), role: "lpShares", binding: { covid: lpCovidHex, authorizingInput: 3 } }
|
|
604
607
|
];
|
|
605
|
-
return { kind: "addLiquidity", inputs, outputs, economics: { dKas: q.dKas, dToken: q.dToken, dShares: q.dShares, newShares: q.newShares }, covids: { poolCovid:
|
|
608
|
+
return { kind: "addLiquidity", inputs, outputs, economics: { dKas: q.dKas, dToken: q.dToken, dShares: q.dShares, newShares: q.newShares }, covids: { poolCovid: poolCovidHex, tokenCovid: tokenCovidHex } };
|
|
606
609
|
}
|
|
607
610
|
function buildRemoveLiquidity(k, tpl, tokenTpl, utxo, lpShares, poolCovid, lpPubkey, q, presenceWitnessIdx, opts = {}) {
|
|
608
611
|
if (lpShares.state.amount !== q.dShares) throw new Error("LP shares UTXO must equal dShares exactly (split first)");
|
|
609
612
|
const dust = opts.tokenDust ?? 1000n;
|
|
610
613
|
const { kasReserve, tokenReserve, tokenCovid, lpCovid } = utxo.state;
|
|
614
|
+
const poolCovidHex = hexOf(poolCovid);
|
|
615
|
+
const tokenCovidHex = hexOf(tokenCovid);
|
|
616
|
+
const lpCovidHex = hexOf(lpCovid);
|
|
611
617
|
const poolTokenOut = covenantIdOwned(poolCovid, q.newToken, false);
|
|
612
618
|
const lpTokenOut = addressPresenceOwned(lpPubkey, q.dToken);
|
|
613
619
|
const poolLpOut = covenantIdOwned(poolCovid, q.dShares, false);
|
|
@@ -625,12 +631,12 @@ function buildRemoveLiquidity(k, tpl, tokenTpl, utxo, lpShares, poolCovid, lpPub
|
|
|
625
631
|
{ transactionId: lpShares.transactionId, index: lpShares.index, value: lpShares.value, scriptPublicKey: kcc20Spk(k, lpSharesRedeem), signatureScript: transferSigScript(k, lpSharesRedeem, lStates, lWitnesses), redeem: lpSharesRedeem, role: "lpShares" }
|
|
626
632
|
];
|
|
627
633
|
const outputs = [
|
|
628
|
-
{ value: q.newKas * SCALE, scriptPublicKey: poolCpSpk(k, newRedeem), role: "pool" },
|
|
629
|
-
{ value: dust, scriptPublicKey: kcc20Spk(k, materializeKcc20Script(tokenTpl, poolTokenOut)), role: "poolToken" },
|
|
630
|
-
{ value: dust, scriptPublicKey: kcc20Spk(k, materializeKcc20Script(tokenTpl, lpTokenOut)), role: "lpToken" },
|
|
631
|
-
{ value: dust, scriptPublicKey: kcc20Spk(k, materializeKcc20Script(tokenTpl, poolLpOut)), role: "poolLpInventory" }
|
|
634
|
+
{ value: q.newKas * SCALE, scriptPublicKey: poolCpSpk(k, newRedeem), role: "pool", binding: { covid: poolCovidHex, authorizingInput: 0 } },
|
|
635
|
+
{ value: dust, scriptPublicKey: kcc20Spk(k, materializeKcc20Script(tokenTpl, poolTokenOut)), role: "poolToken", binding: { covid: tokenCovidHex, authorizingInput: 1 } },
|
|
636
|
+
{ value: dust, scriptPublicKey: kcc20Spk(k, materializeKcc20Script(tokenTpl, lpTokenOut)), role: "lpToken", binding: { covid: tokenCovidHex, authorizingInput: 1 } },
|
|
637
|
+
{ value: dust, scriptPublicKey: kcc20Spk(k, materializeKcc20Script(tokenTpl, poolLpOut)), role: "poolLpInventory", binding: { covid: lpCovidHex, authorizingInput: 2 } }
|
|
632
638
|
];
|
|
633
|
-
return { kind: "removeLiquidity", inputs, outputs, economics: { dShares: q.dShares, dKas: q.dKas, dToken: q.dToken, newShares: q.newShares }, covids: { poolCovid:
|
|
639
|
+
return { kind: "removeLiquidity", inputs, outputs, economics: { dShares: q.dShares, dKas: q.dKas, dToken: q.dToken, newShares: q.newShares }, covids: { poolCovid: poolCovidHex, tokenCovid: tokenCovidHex } };
|
|
634
640
|
}
|
|
635
641
|
function buildBindLp(k, tpl, tokenTpl, utxo, poolCovid, lockedShares, opts = {}) {
|
|
636
642
|
if (utxo.state.lpCovid.length !== 32 || !utxo.state.lpCovid.every((b2) => b2 === 0)) throw new Error("pool lpCovid is already bound \u2014 bindLp is one-time");
|
|
@@ -658,12 +664,13 @@ function buildBindLp(k, tpl, tokenTpl, utxo, poolCovid, lockedShares, opts = {})
|
|
|
658
664
|
const inputs = [
|
|
659
665
|
{ transactionId: utxo.transactionId, index: utxo.index, value: poolValue, scriptPublicKey: poolCpSpk(k, curRedeem), signatureScript: bindSig, redeem: curRedeem, role: "pool" }
|
|
660
666
|
];
|
|
667
|
+
const poolCovidHex = hexOf(poolCovid);
|
|
661
668
|
const outputs = [
|
|
662
|
-
{ value: poolValue, scriptPublicKey: poolCpSpk(k, boundRedeem), role: "pool" },
|
|
663
|
-
{ value: dust, scriptPublicKey: floorSpk, role: "lpFloor" },
|
|
664
|
-
{ value: dust, scriptPublicKey: invSpk, role: "lpInventory" }
|
|
669
|
+
{ value: poolValue, scriptPublicKey: poolCpSpk(k, boundRedeem), role: "pool", binding: { covid: poolCovidHex, authorizingInput: 0 } },
|
|
670
|
+
{ value: dust, scriptPublicKey: floorSpk, role: "lpFloor", binding: { covid: lpCovidHex, authorizingInput: 0 } },
|
|
671
|
+
{ value: dust, scriptPublicKey: invSpk, role: "lpInventory", binding: { covid: lpCovidHex, authorizingInput: 0 } }
|
|
665
672
|
];
|
|
666
|
-
return { kind: "bindLp", inputs, outputs, economics: { lockedShares, inventoryAmount }, covids: { poolCovid:
|
|
673
|
+
return { kind: "bindLp", inputs, outputs, economics: { lockedShares, inventoryAmount }, covids: { poolCovid: poolCovidHex, tokenCovid: hexOf(tokenCovid) }, lpCovidHex, lpInventoryAmount: inventoryAmount };
|
|
667
674
|
}
|
|
668
675
|
|
|
669
676
|
// src/native/curveCpTx.ts
|
|
@@ -721,6 +728,8 @@ function buildCpBuy(k, tpl, tokenTpl, utxo, inventory, curveCovid, buyerPubkey,
|
|
|
721
728
|
if (tokenOut <= 0n || tokenOut >= inventory.amount) throw new Error("invalid tokenOut");
|
|
722
729
|
if (inventory.amount !== utxo.state.tokenReserve) throw new Error("inventory.amount must equal the curve's committed tokenReserve");
|
|
723
730
|
const dust = opts.tokenDust ?? 1000n;
|
|
731
|
+
const curveCovidHex = hexOf2(curveCovid);
|
|
732
|
+
const tokenCovidHex = hexOf2(utxo.state.tokenCovid);
|
|
724
733
|
const newKas = utxo.realKas + kasIn;
|
|
725
734
|
if (newKas > MAX_KAS) throw new Error("buy exceeds the curve max raise (9,000,000 TKAS)");
|
|
726
735
|
const newToken = inventory.amount - tokenOut;
|
|
@@ -746,13 +755,13 @@ function buildCpBuy(k, tpl, tokenTpl, utxo, inventory, curveCovid, buyerPubkey,
|
|
|
746
755
|
})
|
|
747
756
|
];
|
|
748
757
|
const outputs = [
|
|
749
|
-
{ value: newKas, scriptPublicKey: cpSpk(k, newCurveRedeem), role: "curve" },
|
|
750
|
-
{ value: dust, scriptPublicKey: kcc20Spk(k, invOutRedeem), role: "inventory" },
|
|
751
|
-
{ value: dust, scriptPublicKey: kcc20Spk(k, buyerRedeem), role: "recipient" },
|
|
758
|
+
{ value: newKas, scriptPublicKey: cpSpk(k, newCurveRedeem), role: "curve", binding: { covid: curveCovidHex, authorizingInput: 0 } },
|
|
759
|
+
{ value: dust, scriptPublicKey: kcc20Spk(k, invOutRedeem), role: "inventory", binding: { covid: tokenCovidHex, authorizingInput: 1 } },
|
|
760
|
+
{ value: dust, scriptPublicKey: kcc20Spk(k, buyerRedeem), role: "recipient", binding: { covid: tokenCovidHex, authorizingInput: 1 } },
|
|
752
761
|
{ value: padFee3(creatorFee), scriptPublicKey: p2pkSpk(k, tpl.params.creatorFeeOwner), role: "creatorFee" },
|
|
753
762
|
{ value: padFee3(platformFee), scriptPublicKey: p2pkSpk(k, tpl.params.platformFeeOwner), role: "platformFee" }
|
|
754
763
|
];
|
|
755
|
-
return { kind: "buy", inputs, outputs, economics: { kasIn, tokenOut, creatorFee, platformFee, newRealKas: newKas, newTokenReserve: newToken, merged: mergeSum }, covids: { tokenCovid:
|
|
764
|
+
return { kind: "buy", inputs, outputs, economics: { kasIn, tokenOut, creatorFee, platformFee, newRealKas: newKas, newTokenReserve: newToken, merged: mergeSum }, covids: { tokenCovid: tokenCovidHex } };
|
|
756
765
|
}
|
|
757
766
|
function buildCpSell(k, tpl, tokenTpl, utxo, sellerTokens, inventory, curveCovid, traderPubkey, tokenIn, kasOut, presenceWitnessIdx, opts = {}) {
|
|
758
767
|
if (utxo.state.graduated) throw new Error("curve has graduated \u2014 sells are locked");
|
|
@@ -761,6 +770,8 @@ function buildCpSell(k, tpl, tokenTpl, utxo, sellerTokens, inventory, curveCovid
|
|
|
761
770
|
if (kasOut <= 0n || kasOut % SCALE2 !== 0n || kasOut > utxo.realKas) throw new Error("invalid kasOut");
|
|
762
771
|
if (inventory.amount !== utxo.state.tokenReserve) throw new Error("inventory.amount must equal the curve's committed tokenReserve");
|
|
763
772
|
const dust = opts.tokenDust ?? 1000n;
|
|
773
|
+
const curveCovidHex = hexOf2(curveCovid);
|
|
774
|
+
const tokenCovidHex = hexOf2(utxo.state.tokenCovid);
|
|
764
775
|
const sellerIn = sellerTokens.reduce((s, t) => s + t.state.amount, 0n);
|
|
765
776
|
const change = sellerIn - tokenIn;
|
|
766
777
|
if (change < 0n) throw new Error("seller inputs are less than the sell amount");
|
|
@@ -785,13 +796,13 @@ function buildCpSell(k, tpl, tokenTpl, utxo, sellerTokens, inventory, curveCovid
|
|
|
785
796
|
})
|
|
786
797
|
];
|
|
787
798
|
const outputs = [
|
|
788
|
-
{ value: utxo.realKas - kasOut, scriptPublicKey: cpSpk(k, newCurveRedeem), role: "curve" },
|
|
789
|
-
{ value: dust, scriptPublicKey: kcc20Spk(k, invOutRedeem), role: "inventory" },
|
|
799
|
+
{ value: utxo.realKas - kasOut, scriptPublicKey: cpSpk(k, newCurveRedeem), role: "curve", binding: { covid: curveCovidHex, authorizingInput: 0 } },
|
|
800
|
+
{ value: dust, scriptPublicKey: kcc20Spk(k, invOutRedeem), role: "inventory", binding: { covid: tokenCovidHex, authorizingInput: 1 } },
|
|
790
801
|
{ value: padFee3(creatorFee), scriptPublicKey: p2pkSpk(k, tpl.params.creatorFeeOwner), role: "creatorFee" },
|
|
791
802
|
{ value: padFee3(platformFee), scriptPublicKey: p2pkSpk(k, tpl.params.platformFeeOwner), role: "platformFee" }
|
|
792
803
|
];
|
|
793
|
-
if (hasChange) outputs.push({ value: dust, scriptPublicKey: kcc20Spk(k, materializeKcc20Script(tokenTpl, traderChangeOut)), role: "seller" });
|
|
794
|
-
return { kind: "sell", inputs, outputs, economics: { tokenIn, kasOut, change, creatorFee, platformFee, newRealKas: utxo.realKas - kasOut, newTokenReserve: newToken }, covids: { tokenCovid:
|
|
804
|
+
if (hasChange) outputs.push({ value: dust, scriptPublicKey: kcc20Spk(k, materializeKcc20Script(tokenTpl, traderChangeOut)), role: "seller", binding: { covid: tokenCovidHex, authorizingInput: 1 } });
|
|
805
|
+
return { kind: "sell", inputs, outputs, economics: { tokenIn, kasOut, change, creatorFee, platformFee, newRealKas: utxo.realKas - kasOut, newTokenReserve: newToken }, covids: { tokenCovid: tokenCovidHex } };
|
|
795
806
|
}
|
|
796
807
|
function buildCpGraduate(k, tpl, tokenTpl, poolTemplate, utxo, inventory, curveCovid, poolLockedShares, opts = {}) {
|
|
797
808
|
if (utxo.state.graduated) throw new Error("already graduated");
|
|
@@ -822,10 +833,12 @@ function buildCpGraduate(k, tpl, tokenTpl, poolTemplate, utxo, inventory, curveC
|
|
|
822
833
|
{ transactionId: utxo.transactionId, index: utxo.index, value: utxo.realKas, scriptPublicKey: cpSpk(k, curRedeem), signatureScript: graduateSigV2(k, curRedeem, poolState, poolTokens), redeem: curRedeem, role: "curve" },
|
|
823
834
|
{ transactionId: inventory.transactionId, index: inventory.index, value: inventory.value, scriptPublicKey: kcc20Spk(k, invRedeem), signatureScript: transferSigScript(k, invRedeem, [poolTokens], [0]), redeem: invRedeem, role: "inventory" }
|
|
824
835
|
];
|
|
836
|
+
const curveCovidHex = hexOf2(curveCovid);
|
|
837
|
+
const tokenCovidHex = hexOf2(A);
|
|
825
838
|
const outputs = [
|
|
826
|
-
{ value: lockedValue, scriptPublicKey: cpSpk(k, lockedRedeem), role: "curve" },
|
|
827
|
-
{ value: poolKas, scriptPublicKey: poolSpkV, role: "pool" },
|
|
828
|
-
{ value: dust, scriptPublicKey: kcc20Spk(k, poolTokenRedeem), role: "poolToken" },
|
|
839
|
+
{ value: lockedValue, scriptPublicKey: cpSpk(k, lockedRedeem), role: "curve", binding: { covid: curveCovidHex, authorizingInput: 0 } },
|
|
840
|
+
{ value: poolKas, scriptPublicKey: poolSpkV, role: "pool", binding: { covid: poolCovidHex, authorizingInput: 0 } },
|
|
841
|
+
{ value: dust, scriptPublicKey: kcc20Spk(k, poolTokenRedeem), role: "poolToken", binding: { covid: tokenCovidHex, authorizingInput: 1 } },
|
|
829
842
|
{ value: padFee3(gradFee), scriptPublicKey: p2pkSpk(k, tpl.params.platformFeeOwner), role: "gradFee" }
|
|
830
843
|
];
|
|
831
844
|
return { kind: "graduate", inputs, outputs, economics: { poolKas, gradFee, leftover, poolLockedShares }, covids: { tokenCovid: hexOf2(A), poolCovid: poolCovidHex } };
|
|
@@ -909,6 +922,8 @@ function v3SwapSellSig(k, redeem, kasOutUnits, poolTokenOut, traderChangeOut) {
|
|
|
909
922
|
function buildPoolV3SwapKasForToken(k, tpl, tokenTpl, params, utxo, poolCovid, traderPubkey, q, mergeTokens = [], presenceWitnessIdx = 0, opts = {}) {
|
|
910
923
|
const dust = opts.tokenDust ?? 1000n;
|
|
911
924
|
const { kasReserve, tokenReserve, tokenCovid, totalShares, lpCovid } = utxo.state;
|
|
925
|
+
const poolCovidHex = hexOf3(poolCovid);
|
|
926
|
+
const tokenCovidHex = hexOf3(tokenCovid);
|
|
912
927
|
const mergeSum = mergeTokens.reduce((s, t) => s + t.state.amount, 0n);
|
|
913
928
|
const poolTokenOut = covenantIdOwned(poolCovid, q.newToken, false);
|
|
914
929
|
const traderTokenOut = addressPresenceOwned(traderPubkey, q.tokenOut + mergeSum);
|
|
@@ -926,18 +941,20 @@ function buildPoolV3SwapKasForToken(k, tpl, tokenTpl, params, utxo, poolCovid, t
|
|
|
926
941
|
})
|
|
927
942
|
];
|
|
928
943
|
const outputs = [
|
|
929
|
-
{ value: q.newKas * SCALE, scriptPublicKey: poolCpV3Spk(k, newRedeem), role: "pool" },
|
|
930
|
-
{ value: dust, scriptPublicKey: kcc20Spk(k, materializeKcc20Script(tokenTpl, poolTokenOut)), role: "poolToken" },
|
|
931
|
-
{ value: dust, scriptPublicKey: kcc20Spk(k, materializeKcc20Script(tokenTpl, traderTokenOut)), role: "trader" },
|
|
944
|
+
{ value: q.newKas * SCALE, scriptPublicKey: poolCpV3Spk(k, newRedeem), role: "pool", binding: { covid: poolCovidHex, authorizingInput: 0 } },
|
|
945
|
+
{ value: dust, scriptPublicKey: kcc20Spk(k, materializeKcc20Script(tokenTpl, poolTokenOut)), role: "poolToken", binding: { covid: tokenCovidHex, authorizingInput: 1 } },
|
|
946
|
+
{ value: dust, scriptPublicKey: kcc20Spk(k, materializeKcc20Script(tokenTpl, traderTokenOut)), role: "trader", binding: { covid: tokenCovidHex, authorizingInput: 1 } },
|
|
932
947
|
{ value: q.creatorOut, scriptPublicKey: p2pkSpk2(k, params.creatorFeeOwner), role: "creatorFee" },
|
|
933
948
|
{ value: q.platformOut, scriptPublicKey: p2pkSpk2(k, params.platformFeeOwner), role: "platformFee" }
|
|
934
949
|
];
|
|
935
|
-
return { kind: "swapKasForToken", inputs, outputs, economics: { kasIn: q.kasIn, tokenOut: q.tokenOut }, covids: { poolCovid:
|
|
950
|
+
return { kind: "swapKasForToken", inputs, outputs, economics: { kasIn: q.kasIn, tokenOut: q.tokenOut }, covids: { poolCovid: poolCovidHex, tokenCovid: tokenCovidHex } };
|
|
936
951
|
}
|
|
937
952
|
function buildPoolV3SwapTokenForKas(k, tpl, tokenTpl, params, utxo, poolCovid, traderPubkey, traderTokens, q, presenceWitnessIdx, opts = {}) {
|
|
938
953
|
if (traderTokens.length < 1) throw new Error("need at least one trader token");
|
|
939
954
|
const dust = opts.tokenDust ?? 1000n;
|
|
940
955
|
const { kasReserve, tokenReserve, tokenCovid, totalShares, lpCovid } = utxo.state;
|
|
956
|
+
const poolCovidHex = hexOf3(poolCovid);
|
|
957
|
+
const tokenCovidHex = hexOf3(tokenCovid);
|
|
941
958
|
const traderIn = traderTokens.reduce((s, t) => s + t.state.amount, 0n);
|
|
942
959
|
const change = traderIn - q.tokenIn;
|
|
943
960
|
if (change < 0n) throw new Error("trader inputs are less than the sell amount");
|
|
@@ -958,13 +975,13 @@ function buildPoolV3SwapTokenForKas(k, tpl, tokenTpl, params, utxo, poolCovid, t
|
|
|
958
975
|
})
|
|
959
976
|
];
|
|
960
977
|
const outputs = [
|
|
961
|
-
{ value: q.newKas * SCALE, scriptPublicKey: poolCpV3Spk(k, newRedeem), role: "pool" },
|
|
962
|
-
{ value: dust, scriptPublicKey: kcc20Spk(k, materializeKcc20Script(tokenTpl, poolTokenOut)), role: "poolToken" },
|
|
978
|
+
{ value: q.newKas * SCALE, scriptPublicKey: poolCpV3Spk(k, newRedeem), role: "pool", binding: { covid: poolCovidHex, authorizingInput: 0 } },
|
|
979
|
+
{ value: dust, scriptPublicKey: kcc20Spk(k, materializeKcc20Script(tokenTpl, poolTokenOut)), role: "poolToken", binding: { covid: tokenCovidHex, authorizingInput: 1 } },
|
|
963
980
|
{ value: q.creatorOut, scriptPublicKey: p2pkSpk2(k, params.creatorFeeOwner), role: "creatorFee" },
|
|
964
981
|
{ value: q.platformOut, scriptPublicKey: p2pkSpk2(k, params.platformFeeOwner), role: "platformFee" }
|
|
965
982
|
];
|
|
966
|
-
if (hasChange) outputs.push({ value: dust, scriptPublicKey: kcc20Spk(k, materializeKcc20Script(tokenTpl, traderChangeOut)), role: "trader" });
|
|
967
|
-
return { kind: "swapTokenForKas", inputs, outputs, economics: { kasOut: q.kasOut, tokenIn: q.tokenIn }, covids: { poolCovid:
|
|
983
|
+
if (hasChange) outputs.push({ value: dust, scriptPublicKey: kcc20Spk(k, materializeKcc20Script(tokenTpl, traderChangeOut)), role: "trader", binding: { covid: tokenCovidHex, authorizingInput: 1 } });
|
|
984
|
+
return { kind: "swapTokenForKas", inputs, outputs, economics: { kasOut: q.kasOut, tokenIn: q.tokenIn }, covids: { poolCovid: poolCovidHex, tokenCovid: tokenCovidHex } };
|
|
968
985
|
}
|
|
969
986
|
|
|
970
987
|
// src/native/vestingTx.ts
|
|
@@ -979,6 +996,7 @@ __export(vestingTx_exports, {
|
|
|
979
996
|
vestingSpkForState: () => vestingSpkForState
|
|
980
997
|
});
|
|
981
998
|
var VEST_SELECTOR = { claim: 0, claimFinal: 1 };
|
|
999
|
+
var hexOf4 = (u8) => Array.from(u8, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
982
1000
|
function vestedAmount(total, startScore, durationScore, daaScore) {
|
|
983
1001
|
if (daaScore <= startScore) return 0n;
|
|
984
1002
|
const elapsed = BigInt(daaScore - startScore);
|
|
@@ -1004,6 +1022,8 @@ function buildVestingClaim(k, vestTpl, tokenTpl, vestingUtxo, lockedToken, vesti
|
|
|
1004
1022
|
const remaining = total - claimed;
|
|
1005
1023
|
if (release <= 0n || release >= remaining) throw new Error("partial claim must be > 0 and < remaining (use claimFinal to drain)");
|
|
1006
1024
|
const dust = opts.tokenDust ?? 1000n;
|
|
1025
|
+
const vestingCovidHex = hexOf4(vestingCovid);
|
|
1026
|
+
const tokenBinding = opts.tokenCovid ? { covid: opts.tokenCovid, authorizingInput: 1 } : void 0;
|
|
1007
1027
|
const newClaimed = claimed + release, newRemaining = remaining - release;
|
|
1008
1028
|
const curRedeem = materializeVestingScript(vestTpl, claimed);
|
|
1009
1029
|
const newRedeem = materializeVestingScript(vestTpl, newClaimed);
|
|
@@ -1020,20 +1040,22 @@ function buildVestingClaim(k, vestTpl, tokenTpl, vestingUtxo, lockedToken, vesti
|
|
|
1020
1040
|
{ transactionId: lockedToken.transactionId, index: lockedToken.index, value: lockedToken.value, scriptPublicKey: kcc20Spk(k, lockedRedeem), signatureScript: transferSigScript(k, lockedRedeem, [relockState, recipientState], [0]), redeem: lockedRedeem, role: "lockedToken" }
|
|
1021
1041
|
];
|
|
1022
1042
|
const outputs = [
|
|
1023
|
-
{ value: vestingUtxo.value, scriptPublicKey: vestingSpk(k, newRedeem), role: "vesting" },
|
|
1043
|
+
{ value: vestingUtxo.value, scriptPublicKey: vestingSpk(k, newRedeem), role: "vesting", binding: { covid: vestingCovidHex, authorizingInput: 0 } },
|
|
1024
1044
|
// V continuation (claimed bumped)
|
|
1025
|
-
{ value: dust, scriptPublicKey: kcc20Spk(k, materializeKcc20Script(tokenTpl, relockState)), role: "relock" },
|
|
1045
|
+
{ value: dust, scriptPublicKey: kcc20Spk(k, materializeKcc20Script(tokenTpl, relockState)), role: "relock", binding: tokenBinding },
|
|
1026
1046
|
// re-locked (A, V-owned)
|
|
1027
|
-
{ value: dust, scriptPublicKey: kcc20Spk(k, materializeKcc20Script(tokenTpl, recipientState)), role: "recipient" }
|
|
1047
|
+
{ value: dust, scriptPublicKey: kcc20Spk(k, materializeKcc20Script(tokenTpl, recipientState)), role: "recipient", binding: tokenBinding }
|
|
1028
1048
|
// to creator (A, presence)
|
|
1029
1049
|
];
|
|
1030
|
-
return { kind: "claim", inputs, outputs, economics: { release, newClaimed } };
|
|
1050
|
+
return { kind: "claim", inputs, outputs, economics: { release, newClaimed }, covids: opts.tokenCovid ? { tokenCovid: opts.tokenCovid } : {} };
|
|
1031
1051
|
}
|
|
1032
1052
|
function buildVestingClaimFinal(k, vestTpl, tokenTpl, vestingUtxo, lockedToken, vestingCovid, creatorPubkey, claimed, opts = {}) {
|
|
1033
1053
|
const total = BigInt(vestTpl.params.total);
|
|
1034
1054
|
if (claimed < 0n || claimed >= total) throw new Error("nothing left to claim");
|
|
1035
1055
|
const remaining = total - claimed;
|
|
1036
1056
|
const dust = opts.tokenDust ?? 1000n;
|
|
1057
|
+
const vestingCovidHex = hexOf4(vestingCovid);
|
|
1058
|
+
const tokenBinding = opts.tokenCovid ? { covid: opts.tokenCovid, authorizingInput: 1 } : void 0;
|
|
1037
1059
|
const curRedeem = materializeVestingScript(vestTpl, claimed);
|
|
1038
1060
|
const newRedeem = materializeVestingScript(vestTpl, total);
|
|
1039
1061
|
const lockedState = covenantIdOwned(vestingCovid, remaining, false);
|
|
@@ -1047,10 +1069,10 @@ function buildVestingClaimFinal(k, vestTpl, tokenTpl, vestingUtxo, lockedToken,
|
|
|
1047
1069
|
{ transactionId: lockedToken.transactionId, index: lockedToken.index, value: lockedToken.value, scriptPublicKey: kcc20Spk(k, lockedRedeem), signatureScript: transferSigScript(k, lockedRedeem, [recipientState], [0]), redeem: lockedRedeem, role: "lockedToken" }
|
|
1048
1070
|
];
|
|
1049
1071
|
const outputs = [
|
|
1050
|
-
{ value: vestingUtxo.value, scriptPublicKey: vestingSpk(k, newRedeem), role: "vesting" },
|
|
1051
|
-
{ value: dust, scriptPublicKey: kcc20Spk(k, materializeKcc20Script(tokenTpl, recipientState)), role: "recipient" }
|
|
1072
|
+
{ value: vestingUtxo.value, scriptPublicKey: vestingSpk(k, newRedeem), role: "vesting", binding: { covid: vestingCovidHex, authorizingInput: 0 } },
|
|
1073
|
+
{ value: dust, scriptPublicKey: kcc20Spk(k, materializeKcc20Script(tokenTpl, recipientState)), role: "recipient", binding: tokenBinding }
|
|
1052
1074
|
];
|
|
1053
|
-
return { kind: "claimFinal", inputs, outputs, economics: { release: remaining } };
|
|
1075
|
+
return { kind: "claimFinal", inputs, outputs, economics: { release: remaining }, covids: opts.tokenCovid ? { tokenCovid: opts.tokenCovid } : {} };
|
|
1054
1076
|
}
|
|
1055
1077
|
|
|
1056
1078
|
// src/wallet/index.ts
|