paytaca-cli 0.4.1 → 0.5.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 +5 -3
- package/dist/commands/swap.d.ts +19 -0
- package/dist/commands/swap.d.ts.map +1 -0
- package/dist/commands/swap.js +129 -0
- package/dist/commands/swap.js.map +1 -0
- package/dist/commands/token.d.ts.map +1 -1
- package/dist/commands/token.js +140 -1
- package/dist/commands/token.js.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/nostr/store.test.js +12 -4
- package/dist/nostr/store.test.js.map +1 -1
- package/dist/utils/prices.d.ts +46 -0
- package/dist/utils/prices.d.ts.map +1 -0
- package/dist/utils/prices.js +93 -0
- package/dist/utils/prices.js.map +1 -0
- package/dist/utils/prices.test.d.ts +5 -0
- package/dist/utils/prices.test.d.ts.map +1 -0
- package/dist/utils/prices.test.js +62 -0
- package/dist/utils/prices.test.js.map +1 -0
- package/dist/wallet/bch.d.ts +14 -0
- package/dist/wallet/bch.d.ts.map +1 -1
- package/dist/wallet/bch.js +24 -0
- package/dist/wallet/bch.js.map +1 -1
- package/dist/wallet/cauldron/api.d.ts +58 -0
- package/dist/wallet/cauldron/api.d.ts.map +1 -0
- package/dist/wallet/cauldron/api.js +60 -0
- package/dist/wallet/cauldron/api.js.map +1 -0
- package/dist/wallet/cauldron/pools.d.ts +66 -0
- package/dist/wallet/cauldron/pools.d.ts.map +1 -0
- package/dist/wallet/cauldron/pools.js +96 -0
- package/dist/wallet/cauldron/pools.js.map +1 -0
- package/dist/wallet/cauldron/pools.test.d.ts +3 -0
- package/dist/wallet/cauldron/pools.test.d.ts.map +1 -0
- package/dist/wallet/cauldron/pools.test.js +149 -0
- package/dist/wallet/cauldron/pools.test.js.map +1 -0
- package/dist/wallet/cauldron/swap.d.ts +69 -0
- package/dist/wallet/cauldron/swap.d.ts.map +1 -0
- package/dist/wallet/cauldron/swap.js +173 -0
- package/dist/wallet/cauldron/swap.js.map +1 -0
- package/dist/wallet/cauldron/transact.d.ts +98 -0
- package/dist/wallet/cauldron/transact.d.ts.map +1 -0
- package/dist/wallet/cauldron/transact.js +307 -0
- package/dist/wallet/cauldron/transact.js.map +1 -0
- package/package.json +3 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pools.js","sourceRoot":"","sources":["../../../src/wallet/cauldron/pools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pools.test.d.ts","sourceRoot":"","sources":["../../../src/wallet/cauldron/pools.test.ts"],"names":[],"mappings":"AAGA,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,YAAY,CAAA;AAmKnB,YAAY,EAAE,SAAS,EAAE,CAAA"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { NATIVE_BCH_TOKEN_ID } from '@cashlab/common';
|
|
3
|
+
import { binToHex } from '@cashlab/common/libauth.js';
|
|
4
|
+
import { apiPoolToMicroPool, microPoolToPoolV0, poolTradeToOutput, parseRate, } from './pools.js';
|
|
5
|
+
import { attemptTrade, getEntriesSize } from './transact.js';
|
|
6
|
+
// Real active LIFT pool from the riften indexer
|
|
7
|
+
const LIFT_TOKEN_ID = '5932b2fd4915d6a75d3ec53282cd49118149a2176ee67ed68b1111ff0786f7fc';
|
|
8
|
+
const apiPools = [
|
|
9
|
+
{
|
|
10
|
+
owner_p2pkh_addr: 'bitcoincash:zqytt7jjxds269xxm60lprpd8ea786xw3cjfh7pwpk',
|
|
11
|
+
owner_pkh: '08b5fa523360ad14c6de9ff08c2d3e7be3e8ce8e',
|
|
12
|
+
pool_id: '5a6a8da19aecf4198537ac006bcc32bb6c3be514338db813a5610a11ff8c9500',
|
|
13
|
+
sats: 7746405,
|
|
14
|
+
token_id: LIFT_TOKEN_ID,
|
|
15
|
+
tokens: 95698,
|
|
16
|
+
tx_pos: 5,
|
|
17
|
+
txid: 'd49d46592026c574e877c3d6cbad0bbd3302262ae08e318669eaa39d19b94ed5',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
owner_p2pkh_addr: 'bitcoincash:zqwap58dm58cdvz9hgpg83lghd8rjjycn59gkys6cc',
|
|
21
|
+
owner_pkh: '1dd0d0eddd0f86b045ba0283c7e8bb4e3948989d',
|
|
22
|
+
pool_id: '6ac2944e341080772c4ed274033687fd4441d6e6ee976560dae9c83581b9f809',
|
|
23
|
+
sats: 10848211,
|
|
24
|
+
token_id: LIFT_TOKEN_ID,
|
|
25
|
+
tokens: 133950,
|
|
26
|
+
tx_pos: 1,
|
|
27
|
+
txid: '09b048f14763e4a4bba08e236c653e678b79991ec500f8d0a457874de62e3980',
|
|
28
|
+
},
|
|
29
|
+
];
|
|
30
|
+
function pools() {
|
|
31
|
+
return apiPools.map(apiPoolToMicroPool).map(microPoolToPoolV0);
|
|
32
|
+
}
|
|
33
|
+
describe('apiPoolToMicroPool', () => {
|
|
34
|
+
it('maps indexer pool fields onto a MicroPool', () => {
|
|
35
|
+
const micro = apiPoolToMicroPool(apiPools[0]);
|
|
36
|
+
expect(micro.pkh).toBe(apiPools[0].owner_pkh);
|
|
37
|
+
expect(micro.new_utxo_txid).toBe(apiPools[0].txid);
|
|
38
|
+
expect(micro.new_utxo_n).toBe(apiPools[0].tx_pos);
|
|
39
|
+
expect(micro.token_id).toBe(LIFT_TOKEN_ID);
|
|
40
|
+
expect(micro.sats).toBe(apiPools[0].sats);
|
|
41
|
+
expect(micro.token_amount).toBe(apiPools[0].tokens);
|
|
42
|
+
expect(micro.is_withdrawn).toBe(false);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
describe('microPoolToPoolV0', () => {
|
|
46
|
+
it('produces a valid PoolV0 with generated locking bytecode', () => {
|
|
47
|
+
const micro = apiPoolToMicroPool(apiPools[0]);
|
|
48
|
+
const poolV0 = microPoolToPoolV0(micro);
|
|
49
|
+
expect(poolV0.version).toBe('0');
|
|
50
|
+
expect(binToHex(poolV0.parameters.withdraw_pubkey_hash)).toBe(apiPools[0].owner_pkh);
|
|
51
|
+
expect(poolV0.outpoint.index).toBe(apiPools[0].tx_pos);
|
|
52
|
+
expect(binToHex(poolV0.outpoint.txhash)).toBe(apiPools[0].txid);
|
|
53
|
+
expect(poolV0.output.token.token_id).toBe(LIFT_TOKEN_ID);
|
|
54
|
+
expect(poolV0.output.token.amount).toBe(BigInt(apiPools[0].tokens));
|
|
55
|
+
expect(poolV0.output.amount).toBe(BigInt(apiPools[0].sats));
|
|
56
|
+
// Locking bytecode must be non-empty and start with a valid pool script
|
|
57
|
+
expect(poolV0.output.locking_bytecode.length).toBeGreaterThan(0);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
describe('attemptTrade', () => {
|
|
61
|
+
it('computes a best-rate sell trade across pools', () => {
|
|
62
|
+
const result = attemptTrade({
|
|
63
|
+
pools: pools(),
|
|
64
|
+
isBuyingToken: false,
|
|
65
|
+
supply: 1000n, // 10.00 LIFT
|
|
66
|
+
});
|
|
67
|
+
expect(result.entries.length).toBeGreaterThan(0);
|
|
68
|
+
expect(result.summary.supply).toBe(1000n);
|
|
69
|
+
expect(result.summary.demand).toBeGreaterThan(0n);
|
|
70
|
+
expect(result.entries[0].supply_token_id).toBe(LIFT_TOKEN_ID);
|
|
71
|
+
expect(result.entries[0].demand_token_id).toBe(NATIVE_BCH_TOKEN_ID);
|
|
72
|
+
expect(result.summary.trade_fee).toBeGreaterThan(0n);
|
|
73
|
+
});
|
|
74
|
+
it('computes a best-rate buy trade across pools', () => {
|
|
75
|
+
const result = attemptTrade({
|
|
76
|
+
pools: pools(),
|
|
77
|
+
isBuyingToken: true,
|
|
78
|
+
demand: 1000n,
|
|
79
|
+
});
|
|
80
|
+
expect(result.entries[0].supply_token_id).toBe(NATIVE_BCH_TOKEN_ID);
|
|
81
|
+
expect(result.entries[0].demand_token_id).toBe(LIFT_TOKEN_ID);
|
|
82
|
+
expect(result.summary.supply).toBeGreaterThan(0n);
|
|
83
|
+
expect(result.summary.demand).toBe(1000n);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
describe('getEntriesSize', () => {
|
|
87
|
+
it('returns positive input and output sizes', () => {
|
|
88
|
+
const tradeResult = attemptTrade({
|
|
89
|
+
pools: pools(),
|
|
90
|
+
isBuyingToken: false,
|
|
91
|
+
supply: 1000n,
|
|
92
|
+
});
|
|
93
|
+
const sizes = getEntriesSize(tradeResult);
|
|
94
|
+
expect(sizes.inputFees).toBeGreaterThan(0);
|
|
95
|
+
expect(sizes.outputFees).toBeGreaterThan(0);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
describe('poolTradeToOutput', () => {
|
|
99
|
+
it('computes the post-trade pool output', () => {
|
|
100
|
+
const tradeResult = attemptTrade({
|
|
101
|
+
pools: pools(),
|
|
102
|
+
isBuyingToken: false,
|
|
103
|
+
supply: 1000n,
|
|
104
|
+
});
|
|
105
|
+
const entry = tradeResult.entries[0];
|
|
106
|
+
const output = poolTradeToOutput(entry);
|
|
107
|
+
expect(output.amount).toBe(entry.pool.output.amount - entry.demand);
|
|
108
|
+
expect(output.token.amount).toBe(entry.pool.output.token.amount + entry.supply);
|
|
109
|
+
expect(output.token.category).toBe(entry.pool.output.token.token_id);
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
describe('parseRate', () => {
|
|
113
|
+
it('formats a sell price (token→BCH)', () => {
|
|
114
|
+
// rate = supply/demand scaled to denominator 1e13.
|
|
115
|
+
// For a sell: price = (num*10^8/den) / 10^tokenDecimals
|
|
116
|
+
// num=3, den=1, decimals=2 → (3*10^8/1)/100 = 3000000
|
|
117
|
+
const rate = { numerator: 3n, denominator: 1n };
|
|
118
|
+
expect(parseRate(rate, 2, false)).toBe('3000000.00');
|
|
119
|
+
});
|
|
120
|
+
it('formats a buy price (BCH→token)', () => {
|
|
121
|
+
// For a buy: price = (num*10^tokenDecimals/den) / 10^8
|
|
122
|
+
// num=1, den=3, decimals=2 → (1*100/3)/10^8 = 0.00000033
|
|
123
|
+
const rate = { numerator: 1n, denominator: 3n };
|
|
124
|
+
expect(parseRate(rate, 2, true)).toBe('0.00000033');
|
|
125
|
+
});
|
|
126
|
+
it('matches the app formula on a real LIFT trade', () => {
|
|
127
|
+
// SELL: supply=1000 token base units → demand=80378 sats across 2 pools
|
|
128
|
+
const sellTrade = attemptTrade({
|
|
129
|
+
pools: pools(),
|
|
130
|
+
isBuyingToken: false,
|
|
131
|
+
supply: 1000n,
|
|
132
|
+
});
|
|
133
|
+
// rate = supply*1e13/demand
|
|
134
|
+
const sellRate = sellTrade.summary.rate;
|
|
135
|
+
expect(sellRate.denominator).toBe(10000000000000n);
|
|
136
|
+
expect(sellRate.numerator).toBe(124412152579n);
|
|
137
|
+
expect(parseRate(sellRate, 2, false)).toBe('12441.21');
|
|
138
|
+
// BUY: demand=1000 token base units → supply=81569 sats across 2 pools
|
|
139
|
+
const buyTrade = attemptTrade({
|
|
140
|
+
pools: pools(),
|
|
141
|
+
isBuyingToken: true,
|
|
142
|
+
demand: 1000n,
|
|
143
|
+
});
|
|
144
|
+
const buyRate = buyTrade.summary.rate;
|
|
145
|
+
expect(buyRate.numerator).toBe(815690000000000n);
|
|
146
|
+
expect(parseRate(buyRate, 2, true)).toBe('0.00008156');
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
//# sourceMappingURL=pools.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pools.test.js","sourceRoot":"","sources":["../../../src/wallet/cauldron/pools.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cauldron swap orchestration: quote estimation and on-chain execution.
|
|
3
|
+
*
|
|
4
|
+
* This is the generic swap primitive (token ⇄ BCH). Higher-level callers
|
|
5
|
+
* (e.g. an MCP payment wrapper) can use estimateSwap() to price a swap and
|
|
6
|
+
* executeSwap() to broadcast it, mirroring the paytaca-app cauldron flow.
|
|
7
|
+
*/
|
|
8
|
+
import { type PoolV0, type TradeResult } from '@cashlab/cauldron';
|
|
9
|
+
import type { BchWallet } from '../bch.js';
|
|
10
|
+
import { type CauldronTokenData } from './api.js';
|
|
11
|
+
export type SwapDirection = 'buy' | 'sell';
|
|
12
|
+
export interface SwapQuote {
|
|
13
|
+
tokenId: string;
|
|
14
|
+
tokenData: CauldronTokenData;
|
|
15
|
+
direction: SwapDirection;
|
|
16
|
+
isBuyingToken: boolean;
|
|
17
|
+
pools: PoolV0[];
|
|
18
|
+
tradeResult: TradeResult;
|
|
19
|
+
/** Human-readable price. */
|
|
20
|
+
rate: string;
|
|
21
|
+
/** Token amount in base units. */
|
|
22
|
+
tokenAmount: bigint;
|
|
23
|
+
/** BCH amount involved in base units (satoshis). */
|
|
24
|
+
bchAmount: bigint;
|
|
25
|
+
/** Trade fee in satoshis. */
|
|
26
|
+
tradeFee: bigint;
|
|
27
|
+
}
|
|
28
|
+
export interface EstimateSwapOpts {
|
|
29
|
+
/** 64-char hex token category. */
|
|
30
|
+
tokenId: string;
|
|
31
|
+
/** 'buy' = spend BCH to receive tokens, 'sell' = spend tokens to receive BCH. */
|
|
32
|
+
direction: SwapDirection;
|
|
33
|
+
/** Token amount in base units (sell: amount supplied; buy: amount received). */
|
|
34
|
+
amount: bigint;
|
|
35
|
+
}
|
|
36
|
+
export interface ExecuteSwapOpts extends EstimateSwapOpts {
|
|
37
|
+
bchWallet: BchWallet;
|
|
38
|
+
mnemonic: string;
|
|
39
|
+
derivationPath: string;
|
|
40
|
+
}
|
|
41
|
+
export interface SwapResult {
|
|
42
|
+
success: boolean;
|
|
43
|
+
txid?: string;
|
|
44
|
+
transaction?: string;
|
|
45
|
+
error?: string;
|
|
46
|
+
quote?: SwapQuote;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Estimate a swap: fetch pools + token data and compute the best-rate trade.
|
|
50
|
+
*/
|
|
51
|
+
export declare function estimateSwap(opts: EstimateSwapOpts): Promise<SwapQuote>;
|
|
52
|
+
/**
|
|
53
|
+
* Format a SwapQuote for human display.
|
|
54
|
+
*/
|
|
55
|
+
export declare function formatQuote(quote: SwapQuote): string;
|
|
56
|
+
/**
|
|
57
|
+
* Execute a swap: build + sign the trade transaction and broadcast it.
|
|
58
|
+
*/
|
|
59
|
+
export declare function executeSwap(opts: ExecuteSwapOpts): Promise<SwapResult>;
|
|
60
|
+
/**
|
|
61
|
+
* Build + sign the trade transaction (no broadcast).
|
|
62
|
+
*/
|
|
63
|
+
export declare function buildSignedTradeTx(opts: {
|
|
64
|
+
bchWallet: BchWallet;
|
|
65
|
+
mnemonic: string;
|
|
66
|
+
derivationPath: string;
|
|
67
|
+
quote: SwapQuote;
|
|
68
|
+
}): Promise<import("@cashlab/cauldron").TradeTxResult>;
|
|
69
|
+
//# sourceMappingURL=swap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"swap.d.ts","sourceRoot":"","sources":["../../../src/wallet/cauldron/swap.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAe,KAAK,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAE9E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAE1C,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,UAAU,CAAA;AASjB,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,MAAM,CAAA;AAE1C,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,iBAAiB,CAAA;IAC5B,SAAS,EAAE,aAAa,CAAA;IACxB,aAAa,EAAE,OAAO,CAAA;IACtB,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,WAAW,EAAE,WAAW,CAAA;IACxB,4BAA4B;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,kCAAkC;IAClC,WAAW,EAAE,MAAM,CAAA;IACnB,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAA;IACjB,6BAA6B;IAC7B,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,kCAAkC;IAClC,OAAO,EAAE,MAAM,CAAA;IACf,iFAAiF;IACjF,SAAS,EAAE,aAAa,CAAA;IACxB,gFAAgF;IAChF,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,eAAgB,SAAQ,gBAAgB;IACvD,SAAS,EAAE,SAAS,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,cAAc,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAA;IAChB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,SAAS,CAAA;CAClB;AAED;;GAEG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,SAAS,CAAC,CA8CpB;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAwBpD;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC,CAkD5E;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,IAAI,EAAE;IAC7C,SAAS,EAAE,SAAS,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,cAAc,EAAE,MAAM,CAAA;IACtB,KAAK,EAAE,SAAS,CAAA;CACjB,sDA+BA"}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cauldron swap orchestration: quote estimation and on-chain execution.
|
|
3
|
+
*
|
|
4
|
+
* This is the generic swap primitive (token ⇄ BCH). Higher-level callers
|
|
5
|
+
* (e.g. an MCP payment wrapper) can use estimateSwap() to price a swap and
|
|
6
|
+
* executeSwap() to broadcast it, mirroring the paytaca-app cauldron flow.
|
|
7
|
+
*/
|
|
8
|
+
import { ExchangeLab } from '@cashlab/cauldron';
|
|
9
|
+
import { binToHex } from '@cashlab/common/libauth.js';
|
|
10
|
+
import { LibauthHDWallet } from '../keys.js';
|
|
11
|
+
import { fetchPoolsForToken, fetchTokenData, } from './api.js';
|
|
12
|
+
import { apiPoolToMicroPool, microPoolToPoolV0, parseRate } from './pools.js';
|
|
13
|
+
import { attemptTrade, createInputAndOutput, watchtowerUtxosToSpendableCoins, } from './transact.js';
|
|
14
|
+
/**
|
|
15
|
+
* Estimate a swap: fetch pools + token data and compute the best-rate trade.
|
|
16
|
+
*/
|
|
17
|
+
export async function estimateSwap(opts) {
|
|
18
|
+
const { tokenId, direction, amount } = opts;
|
|
19
|
+
const [tokenData, apiPools] = await Promise.all([
|
|
20
|
+
fetchTokenData(tokenId),
|
|
21
|
+
fetchPoolsForToken(tokenId),
|
|
22
|
+
]);
|
|
23
|
+
if (!tokenData) {
|
|
24
|
+
throw new Error(`No cauldron token data found for ${tokenId}`);
|
|
25
|
+
}
|
|
26
|
+
if (apiPools.length === 0) {
|
|
27
|
+
throw new Error(`No active cauldron pools for token ${tokenId}`);
|
|
28
|
+
}
|
|
29
|
+
const pools = apiPools.map(apiPoolToMicroPool).map(microPoolToPoolV0);
|
|
30
|
+
const isBuyingToken = direction === 'buy';
|
|
31
|
+
const tradeResult = attemptTrade({
|
|
32
|
+
pools,
|
|
33
|
+
isBuyingToken,
|
|
34
|
+
supply: isBuyingToken ? undefined : amount,
|
|
35
|
+
demand: isBuyingToken ? amount : undefined,
|
|
36
|
+
});
|
|
37
|
+
// supply/demand semantics depend on direction:
|
|
38
|
+
// sell: supply=token, demand=BCH
|
|
39
|
+
// buy: supply=BCH, demand=token
|
|
40
|
+
const tokenAmount = isBuyingToken
|
|
41
|
+
? tradeResult.summary.demand
|
|
42
|
+
: tradeResult.summary.supply;
|
|
43
|
+
const bchAmount = isBuyingToken
|
|
44
|
+
? tradeResult.summary.supply
|
|
45
|
+
: tradeResult.summary.demand;
|
|
46
|
+
const decimals = tokenData.bcmr.token.decimals;
|
|
47
|
+
return {
|
|
48
|
+
tokenId,
|
|
49
|
+
tokenData,
|
|
50
|
+
direction,
|
|
51
|
+
isBuyingToken,
|
|
52
|
+
pools,
|
|
53
|
+
tradeResult,
|
|
54
|
+
rate: parseRate(tradeResult.summary.rate, decimals, isBuyingToken),
|
|
55
|
+
tokenAmount,
|
|
56
|
+
bchAmount,
|
|
57
|
+
tradeFee: tradeResult.summary.trade_fee,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Format a SwapQuote for human display.
|
|
62
|
+
*/
|
|
63
|
+
export function formatQuote(quote) {
|
|
64
|
+
const { tokenData, direction, rate, tokenAmount, bchAmount, tradeFee } = quote;
|
|
65
|
+
const decimals = tokenData.bcmr.token.decimals;
|
|
66
|
+
const tokenSymbol = tokenData.bcmr.token.symbol || tokenData.display_symbol;
|
|
67
|
+
const tokenFormatted = (Number(tokenAmount) / 10 ** decimals).toFixed(decimals);
|
|
68
|
+
const bchFormatted = (Number(bchAmount) / 10 ** 8).toFixed(8);
|
|
69
|
+
const feeFormatted = (Number(tradeFee) / 10 ** 8).toFixed(8);
|
|
70
|
+
if (direction === 'sell') {
|
|
71
|
+
// Rate semantics (matches paytaca-app): '1 {demandSymbol} ≈ {rate} {supplySymbol}'.
|
|
72
|
+
// Selling tokens → demand is BCH, rate is tokens-per-BCH.
|
|
73
|
+
return [
|
|
74
|
+
`Sell ${tokenFormatted} ${tokenSymbol} for ${bchFormatted} BCH`,
|
|
75
|
+
`Rate: 1 BCH ≈ ${rate} ${tokenSymbol}`,
|
|
76
|
+
`Trade fee: ~${feeFormatted} BCH`,
|
|
77
|
+
].join('\n');
|
|
78
|
+
}
|
|
79
|
+
// Buying tokens → demand is the token, rate is BCH-per-token.
|
|
80
|
+
return [
|
|
81
|
+
`Buy ${tokenFormatted} ${tokenSymbol} for ${bchFormatted} BCH`,
|
|
82
|
+
`Rate: 1 ${tokenSymbol} ≈ ${rate} BCH`,
|
|
83
|
+
`Trade fee: ~${feeFormatted} BCH`,
|
|
84
|
+
].join('\n');
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Execute a swap: build + sign the trade transaction and broadcast it.
|
|
88
|
+
*/
|
|
89
|
+
export async function executeSwap(opts) {
|
|
90
|
+
const { bchWallet, mnemonic, derivationPath } = opts;
|
|
91
|
+
let quote;
|
|
92
|
+
try {
|
|
93
|
+
quote = await estimateSwap(opts);
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
return { success: false, error: err?.message || String(err) };
|
|
97
|
+
}
|
|
98
|
+
let txHex;
|
|
99
|
+
try {
|
|
100
|
+
const tradeTx = await buildSignedTradeTx({
|
|
101
|
+
bchWallet,
|
|
102
|
+
mnemonic,
|
|
103
|
+
derivationPath,
|
|
104
|
+
quote,
|
|
105
|
+
});
|
|
106
|
+
txHex = binToHex(tradeTx.txbin);
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
return { success: false, error: err?.message || String(err), quote };
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
const broadcastResponse = await bchWallet.watchtower.BCH._api.post('broadcast/', { transaction: txHex });
|
|
113
|
+
const data = broadcastResponse.data;
|
|
114
|
+
// Mempool test API compatibility
|
|
115
|
+
if (data?.result) {
|
|
116
|
+
data[data.success ? 'txid' : 'error'] = data.result;
|
|
117
|
+
delete data.result;
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
success: Boolean(data?.success),
|
|
121
|
+
txid: data?.txid,
|
|
122
|
+
transaction: txHex,
|
|
123
|
+
error: data?.error,
|
|
124
|
+
quote,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
catch (err) {
|
|
128
|
+
return {
|
|
129
|
+
success: false,
|
|
130
|
+
transaction: txHex,
|
|
131
|
+
error: err?.message || String(err),
|
|
132
|
+
quote,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Build + sign the trade transaction (no broadcast).
|
|
138
|
+
*/
|
|
139
|
+
export async function buildSignedTradeTx(opts) {
|
|
140
|
+
const { bchWallet, mnemonic, derivationPath, quote } = opts;
|
|
141
|
+
const hdWallet = new LibauthHDWallet(mnemonic, derivationPath, bchWallet.isChipnet ? 'chipnet' : 'mainnet');
|
|
142
|
+
const spendableCoins = await collectSpendableCoins({
|
|
143
|
+
bchWallet,
|
|
144
|
+
hdWallet,
|
|
145
|
+
tokenId: quote.tokenId,
|
|
146
|
+
isBuyingToken: quote.isBuyingToken,
|
|
147
|
+
});
|
|
148
|
+
const { inputCoins, payouts } = createInputAndOutput({
|
|
149
|
+
tradeResult: quote.tradeResult,
|
|
150
|
+
spendableCoins,
|
|
151
|
+
});
|
|
152
|
+
const exlab = new ExchangeLab();
|
|
153
|
+
const tradeTx = exlab.createTradeTx(quote.tradeResult.entries, inputCoins, payouts, null, 1n);
|
|
154
|
+
exlab.verifyTradeTx(tradeTx);
|
|
155
|
+
return tradeTx;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Collect the wallet UTXOs needed for the swap as SpendableCoins.
|
|
159
|
+
* Selling needs the token's UTXOs + BCH; buying needs BCH only.
|
|
160
|
+
*/
|
|
161
|
+
async function collectSpendableCoins(opts) {
|
|
162
|
+
const { bchWallet, hdWallet, tokenId, isBuyingToken } = opts;
|
|
163
|
+
// BCH inputs: all UTXOs, filtered client-side to non-token ones so that
|
|
164
|
+
// other token holdings are never accidentally consumed.
|
|
165
|
+
const [allUtxos, tokenUtxos] = await Promise.all([
|
|
166
|
+
bchWallet.getUtxos(),
|
|
167
|
+
isBuyingToken ? Promise.resolve([]) : bchWallet.getUtxos({ category: tokenId }),
|
|
168
|
+
]);
|
|
169
|
+
const bchUtxos = allUtxos.filter((utxo) => !utxo.is_cashtoken);
|
|
170
|
+
const utxos = [...bchUtxos, ...tokenUtxos];
|
|
171
|
+
return watchtowerUtxosToSpendableCoins({ utxos, wallet: hdWallet });
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=swap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"swap.js","sourceRoot":"","sources":["../../../src/wallet/cauldron/swap.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cauldron trade transaction building.
|
|
3
|
+
*
|
|
4
|
+
* Adapted from: paytaca-app/src/wallet/cauldron/transact.js.
|
|
5
|
+
*
|
|
6
|
+
* Uses @cashlab/cauldron's ExchangeLab to construct a best-rate trade across
|
|
7
|
+
* the active pools, then createInputAndOutput() selects the wallet coins and
|
|
8
|
+
* payout rules needed to fund and settle it. The final signed transaction is
|
|
9
|
+
* produced by ExchangeLab.createTradeTx() (libauth templates).
|
|
10
|
+
*/
|
|
11
|
+
import { ExchangeLab, type PoolV0, type TradeResult } from '@cashlab/cauldron';
|
|
12
|
+
import { type PayoutRule, type SpendableCoin } from '@cashlab/common';
|
|
13
|
+
import type { LibauthHDWallet } from '../keys.js';
|
|
14
|
+
export interface AttemptTradeOpts {
|
|
15
|
+
exlab?: ExchangeLab;
|
|
16
|
+
pools: PoolV0[];
|
|
17
|
+
isBuyingToken: boolean;
|
|
18
|
+
supply?: bigint;
|
|
19
|
+
demand?: bigint;
|
|
20
|
+
txFeePerByte?: bigint;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Attempt a best-rate trade across the given pools.
|
|
24
|
+
*
|
|
25
|
+
* - Selling token → BCH: pass `supply` (token amount in base units).
|
|
26
|
+
* - Buying token with BCH: pass `demand` (token amount in base units to receive).
|
|
27
|
+
*/
|
|
28
|
+
export declare function attemptTrade(opts: AttemptTradeOpts): TradeResult;
|
|
29
|
+
export interface PlatformFee {
|
|
30
|
+
to: string;
|
|
31
|
+
amount: bigint;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Select the wallet coins and payout rules needed to fund + settle a trade.
|
|
35
|
+
* Mirrors paytaca-app createInputAndOutput().
|
|
36
|
+
*/
|
|
37
|
+
export declare function createInputAndOutput(opts: {
|
|
38
|
+
tradeResult: TradeResult;
|
|
39
|
+
spendableCoins: SpendableCoin[];
|
|
40
|
+
platformFee?: PlatformFee;
|
|
41
|
+
tokenOutputSats?: bigint;
|
|
42
|
+
}): {
|
|
43
|
+
inputCoins: SpendableCoin[];
|
|
44
|
+
payouts: PayoutRule[];
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Sum the on-chain byte sizes of the pool inputs and outputs for a trade.
|
|
48
|
+
*/
|
|
49
|
+
export declare function getEntriesSize(tradeResult: TradeResult): {
|
|
50
|
+
inputFees: number;
|
|
51
|
+
outputFees: number;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Build a signed transaction for a trade using test coins, then optionally
|
|
55
|
+
* verify it. Used to validate a trade before broadcasting.
|
|
56
|
+
*/
|
|
57
|
+
export declare function testTradeResult(opts: {
|
|
58
|
+
exlab?: ExchangeLab;
|
|
59
|
+
tradeResult: TradeResult;
|
|
60
|
+
verify?: boolean;
|
|
61
|
+
}): import("@cashlab/cauldron").TradeTxResult;
|
|
62
|
+
/**
|
|
63
|
+
* Convert watchtower UTXOs into @cashlab/common SpendableCoins.
|
|
64
|
+
* Mirrors paytaca-app watchtowerUtxosToSpendableCoins().
|
|
65
|
+
*/
|
|
66
|
+
export interface WatchtowerUtxo {
|
|
67
|
+
txid: string;
|
|
68
|
+
vout: number;
|
|
69
|
+
value: number;
|
|
70
|
+
tokenid?: string;
|
|
71
|
+
amount?: number;
|
|
72
|
+
address_path: string;
|
|
73
|
+
is_cashtoken?: boolean;
|
|
74
|
+
}
|
|
75
|
+
export declare function watchtowerUtxosToSpendableCoins(opts: {
|
|
76
|
+
utxos: WatchtowerUtxo[];
|
|
77
|
+
wallet: LibauthHDWallet;
|
|
78
|
+
}): SpendableCoin[];
|
|
79
|
+
/**
|
|
80
|
+
* On-chain byte size of a transaction input for a given unlocking script.
|
|
81
|
+
* Mirrors cashscript getInputSize().
|
|
82
|
+
*/
|
|
83
|
+
export declare function getInputSize(inputScript: Uint8Array): number;
|
|
84
|
+
interface SizedOutput {
|
|
85
|
+
to: Uint8Array | string;
|
|
86
|
+
amount: bigint;
|
|
87
|
+
token?: {
|
|
88
|
+
category?: string;
|
|
89
|
+
amount: bigint;
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* On-chain byte size of a transaction output.
|
|
94
|
+
* Mirrors cashscript getOutputSize() (string `to` is treated as a CashAddress).
|
|
95
|
+
*/
|
|
96
|
+
export declare function getOutputSize(output: SizedOutput): number;
|
|
97
|
+
export {};
|
|
98
|
+
//# sourceMappingURL=transact.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transact.d.ts","sourceRoot":"","sources":["../../../src/wallet/cauldron/transact.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EACL,WAAW,EAEX,KAAK,MAAM,EACX,KAAK,WAAW,EACjB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAKL,KAAK,UAAU,EACf,KAAK,aAAa,EAEnB,MAAM,iBAAiB,CAAA;AAUxB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AASjD,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,WAAW,CAAA;IACnB,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,aAAa,EAAE,OAAO,CAAA;IACtB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,gBAAgB,GAAG,WAAW,CA8BhE;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;CACf;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE;IACzC,WAAW,EAAE,WAAW,CAAA;IACxB,cAAc,EAAE,aAAa,EAAE,CAAA;IAC/B,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB,GAAG;IAAE,UAAU,EAAE,aAAa,EAAE,CAAC;IAAC,OAAO,EAAE,UAAU,EAAE,CAAA;CAAE,CAkIzD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,WAAW,GAAG;IACxD,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;CACnB,CAcA;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,KAAK,CAAC,EAAE,WAAW,CAAA;IACnB,WAAW,EAAE,WAAW,CAAA;IACxB,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB,6CAmEA;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB;AAED,wBAAgB,+BAA+B,CAAC,IAAI,EAAE;IACpD,KAAK,EAAE,cAAc,EAAE,CAAA;IACvB,MAAM,EAAE,eAAe,CAAA;CACxB,GAAG,aAAa,EAAE,CAmClB;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,UAAU,GAAG,MAAM,CAI5D;AAED,UAAU,WAAW;IACnB,EAAE,EAAE,UAAU,GAAG,MAAM,CAAA;IACvB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;CAC9C;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CA+BzD"}
|