danogo-clmm 0.1.1 → 0.1.3
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 +72 -118
- package/dist/sdk.d.mts +71 -23
- package/dist/sdk.d.ts +71 -23
- package/dist/sdk.js +1 -1
- package/dist/sdk.mjs +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Danogo
|
|
1
|
+
# Danogo CLMM SDK
|
|
2
2
|
|
|
3
3
|
An SDK to calculate and execute swaps on the Danogo liquidity platform on the Cardano network.
|
|
4
4
|
|
|
@@ -12,151 +12,90 @@ npm install danogo-clmm
|
|
|
12
12
|
|
|
13
13
|
This SDK requires:
|
|
14
14
|
- Node.js 18+
|
|
15
|
-
- `@evolution-sdk/evolution` for wallet management and transaction building
|
|
16
|
-
- A Kupmios provider for blockchain data
|
|
17
|
-
- An Ogmios instance for transaction submission
|
|
18
|
-
|
|
19
|
-
### ⚠️ TypeScript Compatibility Note
|
|
20
|
-
|
|
21
|
-
The dependency `@evolution-sdk/evolution` currently ships with some TypeScript type definitions that may cause compilation errors in strict projects.
|
|
22
|
-
|
|
23
|
-
If you encounter type errors originating from `node_modules/@evolution-sdk/evolution`, you can safely enable the following option in your `tsconfig.json`:
|
|
24
|
-
|
|
25
|
-
```json
|
|
26
|
-
{
|
|
27
|
-
"compilerOptions": {
|
|
28
|
-
"skipLibCheck": true
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
```
|
|
15
|
+
- `@evolution-sdk/evolution` version `0.32.2` for wallet management and transaction building
|
|
16
|
+
- A Kupmios provider for blockchain data and transaction submission
|
|
32
17
|
|
|
33
18
|
## Usage
|
|
34
19
|
|
|
35
20
|
### Initialization
|
|
36
21
|
|
|
37
|
-
Initialize the SDK.
|
|
22
|
+
Initialize the SDK and the Evolution client.
|
|
38
23
|
```typescript
|
|
39
|
-
import
|
|
40
|
-
|
|
41
|
-
|
|
24
|
+
import DanogoClmm from "danogo-clmm";
|
|
25
|
+
import { client, preprod } from "@evolution-sdk/evolution";
|
|
26
|
+
|
|
27
|
+
const danogoClmm = new DanogoClmm();
|
|
28
|
+
|
|
29
|
+
const evolutionClient = client(preprod)
|
|
30
|
+
.withKupmios({
|
|
31
|
+
kupoUrl: "your_kupo_url",
|
|
32
|
+
ogmiosUrl: "your_ogmios_url",
|
|
33
|
+
})
|
|
34
|
+
.withSeed({
|
|
35
|
+
mnemonic: "your_seed_phrase",
|
|
36
|
+
accountIndex: 0,
|
|
37
|
+
});
|
|
42
38
|
```
|
|
43
39
|
|
|
44
40
|
### 1. Calculate Swap Output (Quote)
|
|
45
41
|
|
|
46
|
-
Calculate the expected output of a swap without submitting a transaction.
|
|
42
|
+
Calculate the expected output of a swap without submitting a transaction. You can swap through one or more pools to get better price execution.
|
|
47
43
|
|
|
44
|
+
#### Examples
|
|
48
45
|
```typescript
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const client = createClient({
|
|
56
|
-
network: "preprod", // your network
|
|
57
|
-
provider: {
|
|
58
|
-
type: "kupmios", // recommend kupmios
|
|
59
|
-
kupoUrl: "your_kupo_url",
|
|
60
|
-
ogmiosUrl: "your_ogmios_url",
|
|
61
|
-
},
|
|
62
|
-
wallet: {
|
|
63
|
-
type: "seed",
|
|
64
|
-
mnemonic: "your seed phrase",
|
|
65
|
-
accountIndex: 0, // your accountIndex
|
|
46
|
+
const quote = await danogoClmm.calculateSwapOut(evolutionClient, {
|
|
47
|
+
pools: [
|
|
48
|
+
{
|
|
49
|
+
poolOutRef: pool1OutRef,
|
|
50
|
+
deltaAmount: 5_000_000n,
|
|
51
|
+
stakingOutRef: staking1OutRef // required if pool contains ADA and swap for the first time in current epoch
|
|
66
52
|
},
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
deltaAmount: -3_000_000n, // Positive: User sells X -> Buy Y, Negative: User sells Y -> Buy X
|
|
75
|
-
protocolConfigOutRef: new TransactionInput.TransactionInput({
|
|
76
|
-
transactionId: TransactionHash.fromHex("your_tx_hash"),
|
|
77
|
-
index: 0n,
|
|
78
|
-
}),
|
|
79
|
-
stakingOutRef: new TransactionInput.TransactionInput({ // if pool contains ADA
|
|
80
|
-
transactionId: TransactionHash.fromHex("your_tx_hash"),
|
|
81
|
-
index: 1n,
|
|
82
|
-
}),
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
try {
|
|
86
|
-
const expectedOutput = await sdk.calculateSwapOut(client, quoteRequest);
|
|
87
|
-
console.log(`Expected output amount: ${expectedOutput}`);
|
|
88
|
-
} catch (error) {
|
|
89
|
-
console.error("Calculation failed", error);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
53
|
+
{
|
|
54
|
+
poolOutRef: pool2OutRef,
|
|
55
|
+
deltaAmount: 5_000_000n,
|
|
56
|
+
stakingOutRef: staking2OutRef // required if pool contains ADA and swap for the first time in current epoch
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
});
|
|
92
60
|
```
|
|
93
61
|
|
|
94
62
|
### 2. Submit Swap Transaction
|
|
95
63
|
|
|
96
|
-
Build and submit a swap transaction
|
|
64
|
+
Build and submit a swap transaction across one or more pools.
|
|
97
65
|
|
|
66
|
+
#### Examples
|
|
98
67
|
```typescript
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
const client = createClient({
|
|
107
|
-
network: "preprod", // your network
|
|
108
|
-
provider: {
|
|
109
|
-
type: "kupmios", // recommend kupmios
|
|
110
|
-
kupoUrl: "your_kupo_url",
|
|
111
|
-
ogmiosUrl: "your_ogmios_url",
|
|
112
|
-
},
|
|
113
|
-
wallet: {
|
|
114
|
-
type: "seed",
|
|
115
|
-
mnemonic: "your seed phrase",
|
|
116
|
-
accountIndex: 0, // your accountIndex
|
|
68
|
+
const txHash = await danogoClmm.submitSwap(evolutionClient, {
|
|
69
|
+
pools: [
|
|
70
|
+
{
|
|
71
|
+
poolOutRef: pool1OutRef,
|
|
72
|
+
deltaAmount: 5_000_000n,
|
|
73
|
+
minOutChangeAmount: 4_500_000n, // retrieve from calculateSwapOut to avoid slippage
|
|
74
|
+
stakingOutRef: staking1OutRef // required if pool contains ADA and swap for the first time in current epoch
|
|
117
75
|
},
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
poolScriptOutRef: new TransactionInput.TransactionInput({
|
|
128
|
-
transactionId: TransactionHash.fromHex("your_tx_hash"),
|
|
129
|
-
index: 0n,
|
|
130
|
-
}),
|
|
131
|
-
protocolConfigOutRef: new TransactionInput.TransactionInput({
|
|
132
|
-
transactionId: TransactionHash.fromHex("your_tx_hash"),
|
|
133
|
-
index: 0n,
|
|
134
|
-
}),
|
|
135
|
-
stakingOutRef: new TransactionInput.TransactionInput({ // if pool contains ADA
|
|
136
|
-
transactionId: TransactionHash.fromHex("your_tx_hash"),
|
|
137
|
-
index: 1n,
|
|
138
|
-
}),
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
try {
|
|
142
|
-
const txHash = await sdk.submitSwap(client, swapRequest);
|
|
143
|
-
console.log(`Transaction submitted: ${txHash}`);
|
|
144
|
-
} catch (error) {
|
|
145
|
-
console.error("Swap failed", error);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
76
|
+
{
|
|
77
|
+
poolOutRef: pool2OutRef,
|
|
78
|
+
deltaAmount: 5_000_000n,
|
|
79
|
+
minOutChangeAmount: 4_500_000n, // retrieve from calculateSwapOut to avoid slippage
|
|
80
|
+
stakingOutRef: staking2OutRef // required if pool contains ADA and swap for the first time in current epoch
|
|
81
|
+
}
|
|
82
|
+
],
|
|
83
|
+
protocolConfigOutRef: protocolConfigRef
|
|
84
|
+
});
|
|
148
85
|
```
|
|
149
86
|
|
|
150
|
-
|
|
87
|
+
> `protocolConfigOutRef` is optional and defaults to the SDK's internal constants. In rare cases where the protocol configuration has updated but the SDK has not yet been updated, you can manually provide the latest `protocolConfigOutRef` in your request. Refer to `src/constants.ts` for the constants.
|
|
88
|
+
|
|
89
|
+
### 4. Get Pool Info from Ogmios Transaction
|
|
151
90
|
|
|
152
91
|
Extract pool data directly from an Ogmios transaction object.
|
|
153
92
|
|
|
154
93
|
```typescript
|
|
155
|
-
import
|
|
94
|
+
import DanogoClmm from "danogo-clmm";
|
|
156
95
|
import { createChainSynchronizationClient, createInteractionContext } from "@cardano-ogmios/client";
|
|
157
96
|
import { Point } from "@cardano-ogmios/schema";
|
|
158
97
|
|
|
159
|
-
const
|
|
98
|
+
const danogoClmm = new DanogoClmm();
|
|
160
99
|
|
|
161
100
|
async function main() {
|
|
162
101
|
const context = await createInteractionContext(
|
|
@@ -175,7 +114,8 @@ async function main() {
|
|
|
175
114
|
rollForward: async ({ block }, requestNext) => {
|
|
176
115
|
if ("transactions" in block) {
|
|
177
116
|
for (const tx of block.transactions!) {
|
|
178
|
-
const
|
|
117
|
+
const networkId = 0; // 0 for Preprod, 1 for Mainnet
|
|
118
|
+
const pools = danogoClmm.getPoolsFromOgmiosTx(tx, networkId);
|
|
179
119
|
// your logic with pools
|
|
180
120
|
}
|
|
181
121
|
}
|
|
@@ -195,4 +135,18 @@ async function main() {
|
|
|
195
135
|
|
|
196
136
|
await client.resume([checkpoint]);
|
|
197
137
|
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### ⚠️ TypeScript Compatibility Note
|
|
141
|
+
|
|
142
|
+
The dependency `@evolution-sdk/evolution` currently ships with some TypeScript type definitions that may cause compilation errors in strict projects.
|
|
143
|
+
|
|
144
|
+
If you encounter type errors originating from `node_modules/@evolution-sdk/evolution`, you can safely enable the following option in your `tsconfig.json`:
|
|
145
|
+
|
|
146
|
+
```json
|
|
147
|
+
{
|
|
148
|
+
"compilerOptions": {
|
|
149
|
+
"skipLibCheck": true
|
|
150
|
+
}
|
|
151
|
+
}
|
|
198
152
|
```
|
package/dist/sdk.d.mts
CHANGED
|
@@ -51,42 +51,90 @@ interface ConcentratedPool {
|
|
|
51
51
|
totalSwapFee: bigint;
|
|
52
52
|
}
|
|
53
53
|
interface SwapRequest {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
54
|
+
pools: {
|
|
55
|
+
poolOutRef: TransactionInput.TransactionInput;
|
|
56
|
+
deltaAmount: bigint;
|
|
57
|
+
minOutChangeAmount: bigint;
|
|
58
|
+
stakingOutRef?: TransactionInput.TransactionInput;
|
|
59
|
+
}[];
|
|
60
|
+
protocolConfigOutRef?: TransactionInput.TransactionInput;
|
|
60
61
|
}
|
|
61
62
|
interface QuoteSwapRequest {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
pools: {
|
|
64
|
+
poolOutRef: TransactionInput.TransactionInput;
|
|
65
|
+
deltaAmount: bigint;
|
|
66
|
+
stakingOutRef?: TransactionInput.TransactionInput;
|
|
67
|
+
}[];
|
|
68
|
+
protocolConfigOutRef?: TransactionInput.TransactionInput;
|
|
66
69
|
}
|
|
67
70
|
|
|
68
|
-
declare class
|
|
71
|
+
declare class DanogoClmm {
|
|
69
72
|
constructor();
|
|
70
73
|
/**
|
|
71
|
-
* Calculates the expected output amount for a swap
|
|
74
|
+
* Calculates the expected output amount for a swap across multiple liquidity pools.
|
|
72
75
|
*
|
|
73
|
-
* This function retrieves the latest pool
|
|
74
|
-
* to estimate the swap outcome
|
|
76
|
+
* This function retrieves the latest pool states from the blockchain and performs routing
|
|
77
|
+
* calculations to estimate the best swap outcome across multiple pools.
|
|
75
78
|
*
|
|
76
|
-
* @param
|
|
79
|
+
* @param client An initialized SigningClient instance used to query the blockchain.
|
|
77
80
|
* @param request The quote request object containing pool references and the swap amount.
|
|
78
|
-
* - `
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
81
|
+
* - `pools`: Array of pool objects with poolOutRef, deltaAmount, and optional stakingOutRef
|
|
82
|
+
* - `protocolConfigOutRef`: Reference to the protocol configuration UTxO
|
|
83
|
+
* @returns A promise that resolves to a `bigint` representing the estimated total output token amount.
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```typescript
|
|
87
|
+
* const quote = await sdk.calculateSwapOut(client, {
|
|
88
|
+
* pools: [
|
|
89
|
+
* {
|
|
90
|
+
* poolOutRef: pool1OutRef,
|
|
91
|
+
* deltaAmount: 500_000n, // 0.5 ADA to pool 1
|
|
92
|
+
* stakingOutRef: staking1OutRef
|
|
93
|
+
* },
|
|
94
|
+
* {
|
|
95
|
+
* poolOutRef: pool2OutRef,
|
|
96
|
+
* deltaAmount: 500_000n, // 0.5 ADA to pool 2
|
|
97
|
+
* stakingOutRef: staking2OutRef
|
|
98
|
+
* }
|
|
99
|
+
* ],
|
|
100
|
+
* protocolConfigOutRef: protocolConfigRef
|
|
101
|
+
* });
|
|
102
|
+
* ```
|
|
82
103
|
*/
|
|
83
|
-
calculateSwapOut(client: SigningClient, request: QuoteSwapRequest): Promise<bigint>;
|
|
104
|
+
calculateSwapOut(client: SigningClient, request: QuoteSwapRequest): Promise<bigint[]>;
|
|
84
105
|
/**
|
|
85
106
|
* Builds and submits a swap transaction to the network.
|
|
86
107
|
*
|
|
108
|
+
* This method performs a swap across one or more liquidity pools in a single transaction,
|
|
109
|
+
* potentially splitting the input amount across multiple pools for better price execution.
|
|
110
|
+
*
|
|
87
111
|
* @param client An initialized SigningClient instance with a connected wallet.
|
|
88
|
-
* @param request The swap request object containing pool
|
|
112
|
+
* @param request The swap request object containing pool references, swap amount, and minimum output.
|
|
113
|
+
* - `pools`: Array of pool objects with poolOutRef, deltaAmount, and optional stakingOutRef
|
|
114
|
+
* - `minOutChangeAmount`: Minimum acceptable output amount (slippage protection)
|
|
115
|
+
* - `protocolConfigOutRef`: Reference to the protocol configuration UTxO
|
|
89
116
|
* @returns A promise that resolves to the transaction hash.
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```typescript
|
|
120
|
+
* const txHash = await sdk.submitSwap(client, {
|
|
121
|
+
* pools: [
|
|
122
|
+
* {
|
|
123
|
+
* poolOutRef: pool1OutRef,
|
|
124
|
+
* deltaAmount: 500_000n, // 0.5 ADA to pool 1
|
|
125
|
+
* stakingOutRef: staking1OutRef
|
|
126
|
+
* },
|
|
127
|
+
* {
|
|
128
|
+
* poolOutRef: pool2OutRef,
|
|
129
|
+
* deltaAmount: 500_000n, // 0.5 ADA to pool 2
|
|
130
|
+
* stakingOutRef: staking2OutRef
|
|
131
|
+
* }
|
|
132
|
+
* ],
|
|
133
|
+
* poolScriptOutRef: poolScriptRef,
|
|
134
|
+
* minOutChangeAmount: 900_000n, // Minimum 0.9 tokens out
|
|
135
|
+
* protocolConfigOutRef: protocolConfigRef
|
|
136
|
+
* });
|
|
137
|
+
* ```
|
|
90
138
|
*/
|
|
91
139
|
submitSwap(client: SigningClient, request: SwapRequest): Promise<string>;
|
|
92
140
|
/**
|
|
@@ -99,7 +147,7 @@ declare class DanogoSwap {
|
|
|
99
147
|
* @param tx The transaction object conforming to the Ogmios schema.
|
|
100
148
|
* @returns An array of `ConcentratedPool` objects found in the transaction outputs.
|
|
101
149
|
*/
|
|
102
|
-
getPoolsFromOgmiosTx(tx: Transaction,
|
|
150
|
+
getPoolsFromOgmiosTx(tx: Transaction, networkId: number, poolScriptHash?: string): ConcentratedPool[];
|
|
103
151
|
/**
|
|
104
152
|
* Helper function to get the balance of a specific token from user UTXOs
|
|
105
153
|
*/
|
|
@@ -114,4 +162,4 @@ declare class DanogoSwap {
|
|
|
114
162
|
private getStakingRewards;
|
|
115
163
|
}
|
|
116
164
|
|
|
117
|
-
export { type ConcentratedPool, type PoolDatum, type QuoteSwapRequest, type SwapRequest,
|
|
165
|
+
export { type ConcentratedPool, type PoolDatum, type QuoteSwapRequest, type SwapRequest, DanogoClmm as default };
|
package/dist/sdk.d.ts
CHANGED
|
@@ -51,42 +51,90 @@ interface ConcentratedPool {
|
|
|
51
51
|
totalSwapFee: bigint;
|
|
52
52
|
}
|
|
53
53
|
interface SwapRequest {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
54
|
+
pools: {
|
|
55
|
+
poolOutRef: TransactionInput.TransactionInput;
|
|
56
|
+
deltaAmount: bigint;
|
|
57
|
+
minOutChangeAmount: bigint;
|
|
58
|
+
stakingOutRef?: TransactionInput.TransactionInput;
|
|
59
|
+
}[];
|
|
60
|
+
protocolConfigOutRef?: TransactionInput.TransactionInput;
|
|
60
61
|
}
|
|
61
62
|
interface QuoteSwapRequest {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
pools: {
|
|
64
|
+
poolOutRef: TransactionInput.TransactionInput;
|
|
65
|
+
deltaAmount: bigint;
|
|
66
|
+
stakingOutRef?: TransactionInput.TransactionInput;
|
|
67
|
+
}[];
|
|
68
|
+
protocolConfigOutRef?: TransactionInput.TransactionInput;
|
|
66
69
|
}
|
|
67
70
|
|
|
68
|
-
declare class
|
|
71
|
+
declare class DanogoClmm {
|
|
69
72
|
constructor();
|
|
70
73
|
/**
|
|
71
|
-
* Calculates the expected output amount for a swap
|
|
74
|
+
* Calculates the expected output amount for a swap across multiple liquidity pools.
|
|
72
75
|
*
|
|
73
|
-
* This function retrieves the latest pool
|
|
74
|
-
* to estimate the swap outcome
|
|
76
|
+
* This function retrieves the latest pool states from the blockchain and performs routing
|
|
77
|
+
* calculations to estimate the best swap outcome across multiple pools.
|
|
75
78
|
*
|
|
76
|
-
* @param
|
|
79
|
+
* @param client An initialized SigningClient instance used to query the blockchain.
|
|
77
80
|
* @param request The quote request object containing pool references and the swap amount.
|
|
78
|
-
* - `
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
81
|
+
* - `pools`: Array of pool objects with poolOutRef, deltaAmount, and optional stakingOutRef
|
|
82
|
+
* - `protocolConfigOutRef`: Reference to the protocol configuration UTxO
|
|
83
|
+
* @returns A promise that resolves to a `bigint` representing the estimated total output token amount.
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```typescript
|
|
87
|
+
* const quote = await sdk.calculateSwapOut(client, {
|
|
88
|
+
* pools: [
|
|
89
|
+
* {
|
|
90
|
+
* poolOutRef: pool1OutRef,
|
|
91
|
+
* deltaAmount: 500_000n, // 0.5 ADA to pool 1
|
|
92
|
+
* stakingOutRef: staking1OutRef
|
|
93
|
+
* },
|
|
94
|
+
* {
|
|
95
|
+
* poolOutRef: pool2OutRef,
|
|
96
|
+
* deltaAmount: 500_000n, // 0.5 ADA to pool 2
|
|
97
|
+
* stakingOutRef: staking2OutRef
|
|
98
|
+
* }
|
|
99
|
+
* ],
|
|
100
|
+
* protocolConfigOutRef: protocolConfigRef
|
|
101
|
+
* });
|
|
102
|
+
* ```
|
|
82
103
|
*/
|
|
83
|
-
calculateSwapOut(client: SigningClient, request: QuoteSwapRequest): Promise<bigint>;
|
|
104
|
+
calculateSwapOut(client: SigningClient, request: QuoteSwapRequest): Promise<bigint[]>;
|
|
84
105
|
/**
|
|
85
106
|
* Builds and submits a swap transaction to the network.
|
|
86
107
|
*
|
|
108
|
+
* This method performs a swap across one or more liquidity pools in a single transaction,
|
|
109
|
+
* potentially splitting the input amount across multiple pools for better price execution.
|
|
110
|
+
*
|
|
87
111
|
* @param client An initialized SigningClient instance with a connected wallet.
|
|
88
|
-
* @param request The swap request object containing pool
|
|
112
|
+
* @param request The swap request object containing pool references, swap amount, and minimum output.
|
|
113
|
+
* - `pools`: Array of pool objects with poolOutRef, deltaAmount, and optional stakingOutRef
|
|
114
|
+
* - `minOutChangeAmount`: Minimum acceptable output amount (slippage protection)
|
|
115
|
+
* - `protocolConfigOutRef`: Reference to the protocol configuration UTxO
|
|
89
116
|
* @returns A promise that resolves to the transaction hash.
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```typescript
|
|
120
|
+
* const txHash = await sdk.submitSwap(client, {
|
|
121
|
+
* pools: [
|
|
122
|
+
* {
|
|
123
|
+
* poolOutRef: pool1OutRef,
|
|
124
|
+
* deltaAmount: 500_000n, // 0.5 ADA to pool 1
|
|
125
|
+
* stakingOutRef: staking1OutRef
|
|
126
|
+
* },
|
|
127
|
+
* {
|
|
128
|
+
* poolOutRef: pool2OutRef,
|
|
129
|
+
* deltaAmount: 500_000n, // 0.5 ADA to pool 2
|
|
130
|
+
* stakingOutRef: staking2OutRef
|
|
131
|
+
* }
|
|
132
|
+
* ],
|
|
133
|
+
* poolScriptOutRef: poolScriptRef,
|
|
134
|
+
* minOutChangeAmount: 900_000n, // Minimum 0.9 tokens out
|
|
135
|
+
* protocolConfigOutRef: protocolConfigRef
|
|
136
|
+
* });
|
|
137
|
+
* ```
|
|
90
138
|
*/
|
|
91
139
|
submitSwap(client: SigningClient, request: SwapRequest): Promise<string>;
|
|
92
140
|
/**
|
|
@@ -99,7 +147,7 @@ declare class DanogoSwap {
|
|
|
99
147
|
* @param tx The transaction object conforming to the Ogmios schema.
|
|
100
148
|
* @returns An array of `ConcentratedPool` objects found in the transaction outputs.
|
|
101
149
|
*/
|
|
102
|
-
getPoolsFromOgmiosTx(tx: Transaction,
|
|
150
|
+
getPoolsFromOgmiosTx(tx: Transaction, networkId: number, poolScriptHash?: string): ConcentratedPool[];
|
|
103
151
|
/**
|
|
104
152
|
* Helper function to get the balance of a specific token from user UTXOs
|
|
105
153
|
*/
|
|
@@ -114,4 +162,4 @@ declare class DanogoSwap {
|
|
|
114
162
|
private getStakingRewards;
|
|
115
163
|
}
|
|
116
164
|
|
|
117
|
-
export { type ConcentratedPool, type PoolDatum, type QuoteSwapRequest, type SwapRequest,
|
|
165
|
+
export { type ConcentratedPool, type PoolDatum, type QuoteSwapRequest, type SwapRequest, DanogoClmm as default };
|
package/dist/sdk.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var N=Object.defineProperty;var K=Object.getOwnPropertyDescriptor;var Z=Object.getOwnPropertyNames;var tt=Object.prototype.hasOwnProperty;var et=(n,e)=>{for(var t in e)N(n,t,{get:e[t],enumerable:!0})},nt=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of Z(e))!tt.call(n,o)&&o!==t&&N(n,o,{get:()=>e[o],enumerable:!(r=K(e,o))||r.enumerable});return n};var ot=n=>nt(N({},"__esModule",{value:!0}),n);var at={};et(at,{default:()=>st});module.exports=ot(at);var E=require("@evolution-sdk/evolution"),T=require("@evolution-sdk/evolution/ScriptHash"),d=require("@evolution-sdk/evolution/Assets");var H=require("@evolution-sdk/evolution");function P(n,e){let r=(n>=0n?n:n+(1n<<256n)).toString(16);r.length%2&&(r="0"+r);let o=r.length/2;if(o>e)throw new Error(`Number ${n} requires ${o} bytes, but target length is ${e}.`);let s=new Uint8Array(e),i=e-o;for(let a=0;a<o;a++)s[a+i]=parseInt(r.slice(a*2,a*2+2),16);return s}var O=(n,e,t,r)=>{try{let o=s=>{let i=3n,a=P(r?t:s,1),g=P(s,1),l=P(i,1),u=P(0n,1),f=P(e[0],32),w=a.length+l.length+g.length+u.length+f.length,m=new Uint8Array(w),c=0;m.set(a,c),c+=a.length,m.set(l,c),c+=l.length,m.set(g,c),c+=g.length,m.set(u,c),c+=u.length,m.set(f,c);let y=Buffer.from(m).toString("hex");return H.Data.fromCBORHex("5824"+y)};return{all:s=>{if(!s.length)throw new Error("swapTokensRedeemer batch all called with empty indexedInputs");let i=BigInt(s[0].index);return o(i)},inputs:n}}catch(o){throw console.error("Error creating pool redeemer:",o),o}};var I=require("@evolution-sdk/evolution"),$=require("@evolution-sdk/evolution/InlineDatum"),M=n=>{let e=[new Uint8Array(Buffer.from(n.tokenX.slice(0,56),"hex")),new Uint8Array(Buffer.from(n.tokenX.slice(57),"hex"))],t=[new Uint8Array(Buffer.from(n.tokenY.slice(0,56),"hex")),new Uint8Array(Buffer.from(n.tokenY.slice(57),"hex"))],r=I.Data.constr(0n,[n.sqrtLowerPriceNum,n.sqrtLowerPriceDen]),o=I.Data.constr(0n,[n.sqrtUpperPriceNum,n.sqrtUpperPriceDen]),s=I.Data.constr(0n,[e,t,BigInt(n.lpFeeRate),n.platformFeeX,n.platformFeeY,n.totalSwapFee,r,o,n.minXChange,n.minYChange,n.circulatingLPToken,BigInt(n.lastWithdrawEpoch)]);return new $.InlineDatum({data:s})};var k=n=>{let e;if(typeof n=="string")e=I.CBOR.fromCBORHex(n);else{let s=n.data,i=I.Data.toCBORHex(s);e=I.CBOR.fromCBORHex(i)}let t=e._tag==="Tag"?e.value:e;if(!Array.isArray(t))throw new Error("Invalid datum structure: expected array of fields");let r=s=>{let i=s._tag==="Tag"?s.value:s;if(Array.isArray(i)&&i.length===2){let a=i[0]instanceof Uint8Array?i[0]:new Uint8Array(i[0]),g=i[1]instanceof Uint8Array?i[1]:new Uint8Array(i[1]),l=Buffer.from(a).toString("hex"),u=Buffer.from(g).toString("hex");return l===""&&u===""?"lovelace":l+"."+u}throw new Error("Invalid AssetClass structure")},o=s=>{let i=s._tag==="Tag"?s.value:s;if(Array.isArray(i)&&i.length===2)return{num:BigInt(i[0]),den:BigInt(i[1])};throw new Error("Invalid Ratio structure")};return{tokenX:r(t[0]),tokenY:r(t[1]),lpFeeRate:Number(t[2]),platformFeeX:BigInt(t[3]),platformFeeY:BigInt(t[4]),totalSwapFee:BigInt(t[5]),sqrtLowerPriceNum:o(t[6]).num,sqrtLowerPriceDen:o(t[6]).den,sqrtUpperPriceNum:o(t[7]).num,sqrtUpperPriceDen:o(t[7]).den,minXChange:BigInt(t[8]),minYChange:BigInt(t[9]),circulatingLPToken:BigInt(t[10]),lastWithdrawEpoch:Number(t[11])}},v=n=>{let e,t=I.Data.toCBORHex(n.data);e=I.CBOR.fromCBORHex(t);let r=e._tag==="Tag"?e.value:e;if(!Array.isArray(r))throw new Error("Invalid datum structure: expected array of fields");return{platformFeeRate:BigInt(r[0]),swapFee:BigInt(r[1])}};var A=require("@evolution-sdk/evolution");function R(n){if(n==="lovelace")return{unit:"lovelace"};let e=n.indexOf("."),t=e===-1?n:n.slice(0,e),r=e===-1?"":n.slice(e+1),o=A.Bytes.fromHex(t),s=new A.PolicyId.PolicyId({hash:o}),i=r?A.Bytes.fromHex(r):new Uint8Array(0),a=new A.AssetName.AssetName({bytes:i});return{policyId:s,assetName:a,unit:n}}var _=n=>{if(!n||Object.keys(n).length===0)return[];let e=[];for(let[t,r]of Object.entries(n)){if(t==="ada")continue;let o=[];for(let[s,i]of Object.entries(r))o.push({name:s,value:i});e.push({policyId:t,assets:o})}return e};var V=(n,e)=>{let t=432e6,r=1647899091e3,o=328;return e!==1&&(t=18e5),Math.floor((n-r)/t)+o};function S(n,e,t,r,o=0n,s){let i=r<0n?-r:r,a=t.tokenX==="lovelace"?3000000n+BigInt(t.totalSwapFee):0n,g=BigInt(n)-BigInt(t.platformFeeX)+o-a,l=BigInt(e)-BigInt(t.platformFeeY),u=rt(g,l,[BigInt(t.sqrtLowerPriceNum),BigInt(t.sqrtLowerPriceDen)],[BigInt(t.sqrtUpperPriceNum),BigInt(t.sqrtUpperPriceDen)]),f=j(u[0]*BigInt(t.sqrtUpperPriceDen),u[1]*BigInt(t.sqrtUpperPriceNum))+g,w=j(u[0]*BigInt(t.sqrtLowerPriceNum),u[1]*BigInt(t.sqrtLowerPriceDen))+l;return r>0n?W(i,f,w,l,BigInt(t.lpFeeRate),s):W(i,w,f,g,BigInt(t.lpFeeRate),s)}var W=(n,e,t,r,o,s)=>{let i=10000n,g=n*o/i*BigInt(s)/10000n,l=i-o,u=e*i+n*l,f=e*t,m=(t*u-f*i)/u;if(m>r)throw new Error("pool out exceeded");return[m,g]},rt=(n,e,t,r)=>{let o=t[1]*r[1],s=t[0]*r[0],i=(e*o-n*s)*(e*o-n*s),a=4n*n*e*t[1]*t[1]*r[0]*r[0],g=it(i+a),l=e*o+n*s+g,u=2n*(r[0]*t[1]-r[1]*t[0]);return[l,u]};function it(n){if(n<0n)throw new Error("Square root of negative number");if(n<2n)return n;let e=n,t=e+n/e>>1n;for(;t<e;)e=t,t=e+n/e>>1n;return e}function j(n,e){if(e===0n)throw new Error("Division by zero");let t=n/e;return n%e===0n||n<0n!=e<0n?t:t+1n}function G(n,e){let r=[...e].sort((o,s)=>o.transactionId===s.transactionId?o.index<s.index?-1:1:o.transactionId<s.transactionId?-1:1).findIndex(o=>o.transactionId===n.transactionId&&o.index===n.index);if(r===-1)throw new Error("Protocol config out ref not found in reference inputs");return BigInt(r)}var q=class{constructor(){}async calculateSwapOut(e,t){if(!e||!e.address)throw new Error("Please connect a wallet first.");let r=(await e.address()).networkId,o=(await e.getUtxosByOutRef([t.poolOutRef]))[0],s=null;if(t.stakingOutRef&&(s=(await e.getUtxosByOutRef([t.stakingOutRef]))[0]),!o.datumOption)throw new Error("Pool input UTxO does not contain a datum.");let i=(await e.getUtxosByOutRef([t.protocolConfigOutRef]))[0];if(!i.datumOption)throw new Error("Protocol config UTxO does not contain a datum.");let a=v(i.datumOption),g=k(o.datumOption),l=R(g.tokenX),u=R(g.tokenY),f=o.assets.lovelace,w=h=>h.unit==="lovelace"?f:(0,d.quantityOf)(o.assets,h.policyId,h.assetName),{rewardAmount:m}=await this.getStakingRewards(e,r,s,l),[c,y]=S(w(l),w(u),g,t.deltaAmount,m,a.platformFeeRate);return c}async submitSwap(e,t){if(!e||!e.address)throw new Error("Please connect a wallet first.");let r=(await e.address()).networkId,o=(await e.getUtxosByOutRef([t.poolOutRef]))[0],s=(await e.getUtxosByOutRef([t.poolScriptOutRef]))[0],i=null;if(t.stakingOutRef&&(i=(await e.getUtxosByOutRef([t.stakingOutRef]))[0]),!o.datumOption)throw new Error("Pool input UTxO does not contain a datum.");let a=(await e.getUtxosByOutRef([t.protocolConfigOutRef]))[0];if(!a.datumOption)throw new Error("Protocol config UTxO does not contain a datum.");let g=v(a.datumOption),l=k(o.datumOption),u=R(l.tokenX),f=R(l.tokenY),w=o.assets.lovelace,m=C=>C.unit==="lovelace"?w:(0,d.quantityOf)(o.assets,C.policyId,C.assetName),c=t.deltaAmount,y=c>0?u:f,h=c>0?f:u,p=e.newTx(),x=await this.getUserTokenBalance(e,y),D=c<0n?-c:c;if(x<D)throw new Error(`Insufficient ${y.unit} balance. Required: ${D}, Available: ${x}`);p=p.readFrom({referenceInputs:[s,a]}),i&&(p=p.readFrom({referenceInputs:[i]}));let{rewardAmount:U,stakingRewardAddress:L}=await this.getStakingRewards(e,r,i,u),[B,b]=S(m(u),m(f),l,c,U,g.platformFeeRate);if(B<t.minOutChangeAmount)throw new Error(`Slippage too high. Expected at least ${t.minOutChangeAmount} but got ${B}`);let X=V(Date.now(),r),Q=M({...l,platformFeeX:BigInt(l.platformFeeX)+(y.unit===u.unit?b:0n),platformFeeY:BigInt(l.platformFeeY)+(y.unit===f.unit?b:0n),lastWithdrawEpoch:X,totalSwapFee:BigInt(l.totalSwapFee)+BigInt(g.swapFee)}),z=this.buildDeltaAssets(y,h,c,BigInt(B),BigInt(g.swapFee)),J=(0,d.merge)(o.assets,z);p=p.payToAddress({address:o.address,assets:J,datum:Q}),p=p.attachMetadata({label:674n,metadata:new Map([["msg",["Danogo Liquidity Pair: Swap"]]])});let Y=[s,a];i&&Y.push(i);let F=G(a,Y);return p=p.collectFrom({inputs:[o],redeemer:O([o],[c],F,!1)}),p=p.withdraw({stakeCredential:(0,T.fromScript)(s.scriptRef),amount:0n,redeemer:O([o],[c],F,!0)}),u.unit==="lovelace"&&X>l.lastWithdrawEpoch&&L&&(p=p.withdraw({stakeCredential:(0,T.fromScript)(i.scriptRef),amount:U,redeemer:O([o],[c],F,!1)})),p.setValidity({from:BigInt(Date.now()-12e4),to:BigInt(Date.now()+24e4)}),(await(await(await p.build({debug:!0})).sign()).submit()).toString()}getPoolsFromOgmiosTx(e,t){let r=[];return e.outputs.forEach((o,s)=>{let i=o.value,a=i[t];if(a&&o.datum){for(let[g,l]of Object.entries(a))if(l===1n){let u=t+g,f=`${e.id}#${s}`,w=i.ada.lovelace,m=_(i),c=k(o.datum),y=c.tokenX,h=c.tokenY,p=x=>{if(x==="lovelace"||x==="")return w;let D=x.slice(0,56),U=x.slice(56),B=m.find(b=>b.policyId===D)?.assets.find(b=>b.name===U);return B?B.value:0n};r.push({outRef:f,address:o.address,coin:w,multiAssets:m,validityNft:u,tokenA:y,tokenAReserve:p(y),tokenB:h,tokenBReserve:p(h),lpFeeRate:c.lpFeeRate,priceLowerNum:c.sqrtLowerPriceNum,priceLowerDen:c.sqrtLowerPriceDen,priceUpperNum:c.sqrtUpperPriceNum,priceUpperDen:c.sqrtUpperPriceDen,platformFeeA:c.platformFeeX,platformFeeB:c.platformFeeY,minAChange:c.minXChange,minBChange:c.minYChange,lpTokenTotalSupply:c.circulatingLPToken,lastWithdrawEpoch:c.lastWithdrawEpoch,totalSwapFee:c.totalSwapFee})}}}),r}async getUserTokenBalance(e,t){return(await e.getWalletUtxos()).reduce((o,s)=>o+(t.unit==="lovelace"?s.assets.lovelace:(0,d.quantityOf)(s.assets,t.policyId,t.assetName)||0n),0n)}buildDeltaAssets(e,t,r,o,s){let i=r>0n?r:-r,a;if(e.unit==="lovelace"?a=(0,d.fromLovelace)(i+s):a=(0,d.fromAsset)(e.policyId,e.assetName,i,s),t.unit==="lovelace")a=(0,d.subtractLovelace)(a,o);else{let g=(0,d.fromAsset)(t.policyId,t.assetName,-o);a=(0,d.merge)(a,g)}return a}async getStakingRewards(e,t,r,o){if(o.unit!=="lovelace")return{rewardAmount:0n};let s=new E.RewardAccount.RewardAccount({networkId:t,stakeCredential:(0,T.fromScript)(r.scriptRef)}),i=E.RewardAccount.toBech32(s);return{rewardAmount:(await e.getDelegation(i)).rewards,stakingRewardAddress:i}}},st=q;
|
|
1
|
+
var G=Object.defineProperty;var ut=Object.getOwnPropertyDescriptor;var lt=Object.getOwnPropertyNames;var pt=Object.prototype.hasOwnProperty;var ft=(n,t)=>{for(var e in t)G(n,e,{get:t[e],enumerable:!0})},mt=(n,t,e,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of lt(t))!pt.call(n,o)&&o!==e&&G(n,o,{get:()=>t[o],enumerable:!(r=ut(t,o))||r.enumerable});return n};var dt=n=>mt(G({},"__esModule",{value:!0}),n);var Bt={};ft(Bt,{default:()=>Rt});module.exports=dt(Bt);var z=require("@evolution-sdk/evolution"),Y=require("@evolution-sdk/evolution/ScriptHash"),b=require("@evolution-sdk/evolution/Assets");function C(n,t){let r=(n>=0n?n:n+(1n<<256n)).toString(16);r.length%2&&(r="0"+r);let o=r.length/2;if(o>t)throw new Error(`Number ${n} requires ${o} bytes, but target length is ${t}.`);let i=new Uint8Array(t),s=t-o;for(let a=0;a<o;a++)i[a+s]=parseInt(r.slice(a*2,a*2+2),16);return i}var v=(n,t,e,r)=>{try{let o=(i,s)=>{let a=3n,m=C(n?i:r,1),l=C(a,1),p=t.map((A,y)=>{let R=s.find(h=>h.utxo.transactionId===A.transactionId&&h.utxo.index===A.index);if(!R)throw new Error(`Pool UTxO at ${y} not found in indexedInputs`);if(e[y]===void 0)throw new Error(`deltaAmount for poolOutIdx ${y} is undefined`);let w=C(BigInt(R.index),1),O=C(BigInt(y),1),g=C(e[y],32);return{poolInBytes:w,poolOutBytes:O,amountBytes:g}}),I=2+34*p.length,u=new Uint8Array(I),d=0;u.set(m,d),d+=m.length,u.set(l,d),d+=l.length;for(let A of p)u.set(A.poolInBytes,d),d+=A.poolInBytes.length,u.set(A.poolOutBytes,d),d+=A.poolOutBytes.length,u.set(A.amountBytes,d),d+=A.amountBytes.length;return u};return{all:i=>{if(!i.length)throw new Error("swapTokensRedeemer batch all called with empty indexedInputs");let s=null;if(n&&(s=i.find(a=>a.utxo.transactionId===n.transactionId&&a.utxo.index===n.index),!s))throw new Error("Target pool UTxO is not found in poolInUTxOs");return o(s?.index,i)},inputs:t}}catch(o){throw console.error("Error creating pool redeemer:",o),o}};var B=require("@evolution-sdk/evolution"),tt=require("@evolution-sdk/evolution/InlineDatum");var L=require("@evolution-sdk/evolution"),x="lovelace",J=432e6,gt="64d111b957e7d7848ffdde5149aa77fa4090a7fa1ad0ac108067900614848501#0",wt="d8b69fc53637bcfadbc4469083f706bc293f4d9d2296646c5ca167bb",At="2cafd7c92f7093e5229af274be83dea660b0590b4174bbed79ba662b44fbd1ee#0",K=18e5,It="2e19cca74e3badcab26aef7574aa1885ba97228a254ca227ba2f79f2b75fd136#0",xt="04041c3c6ba87b33f2c9eb7f7dbeae3b26003c3e199d438bb99932a2",yt="3775af36f485f9c97101ee5b9b360c34f0f8e12186bc9060f358b7fc8ce468a4#0",H=n=>n===1?{poolScriptOutRef:q(gt),poolScriptHash:wt,protocolScriptOutRef:q(At)}:{poolScriptOutRef:q(It),poolScriptHash:xt,protocolScriptOutRef:q(yt)},q=n=>{if(!n)return;let[t,e]=n.split("#");return new L.TransactionInput.TransactionInput({transactionId:L.TransactionHash.fromHex(t),index:BigInt(e)})};var et=n=>{let t=[new Uint8Array(Buffer.from(n.tokenX.slice(0,56),"hex")),new Uint8Array(Buffer.from(n.tokenX.slice(57),"hex"))],e=[new Uint8Array(Buffer.from(n.tokenY.slice(0,56),"hex")),new Uint8Array(Buffer.from(n.tokenY.slice(57),"hex"))],r=B.Data.constr(0n,[n.sqrtLowerPriceNum,n.sqrtLowerPriceDen]),o=B.Data.constr(0n,[n.sqrtUpperPriceNum,n.sqrtUpperPriceDen]),i=B.Data.constr(0n,[t,e,BigInt(n.lpFeeRate),n.platformFeeX,n.platformFeeY,n.totalSwapFee,r,o,n.minXChange,n.minYChange,n.circulatingLPToken,BigInt(n.lastWithdrawEpoch)]);return new tt.InlineDatum({data:i})};var X=n=>{let t;if(typeof n=="string")t=B.CBOR.fromCBORHex(n);else{let i=n.data,s=B.Data.toCBORHex(i);t=B.CBOR.fromCBORHex(s)}let e=t._tag==="Tag"?t.value:t;if(!Array.isArray(e))throw new Error("Invalid datum structure: expected array of fields");let r=i=>{let s=i._tag==="Tag"?i.value:i;if(Array.isArray(s)&&s.length===2){let a=s[0]instanceof Uint8Array?s[0]:new Uint8Array(s[0]),m=s[1]instanceof Uint8Array?s[1]:new Uint8Array(s[1]),l=Buffer.from(a).toString("hex"),p=Buffer.from(m).toString("hex");return l===""&&p===""?x:l+"."+p}throw new Error("Invalid AssetClass structure")},o=i=>{let s=i._tag==="Tag"?i.value:i;if(Array.isArray(s)&&s.length===2)return{num:BigInt(s[0]),den:BigInt(s[1])};throw new Error("Invalid Ratio structure")};return{tokenX:r(e[0]),tokenY:r(e[1]),lpFeeRate:Number(e[2]),platformFeeX:BigInt(e[3]),platformFeeY:BigInt(e[4]),totalSwapFee:BigInt(e[5]),sqrtLowerPriceNum:o(e[6]).num,sqrtLowerPriceDen:o(e[6]).den,sqrtUpperPriceNum:o(e[7]).num,sqrtUpperPriceDen:o(e[7]).den,minXChange:BigInt(e[8]),minYChange:BigInt(e[9]),circulatingLPToken:BigInt(e[10]),lastWithdrawEpoch:Number(e[11])}},j=n=>{let t,e=B.Data.toCBORHex(n.data);t=B.CBOR.fromCBORHex(e);let r=t._tag==="Tag"?t.value:t;if(!Array.isArray(r))throw new Error("Invalid datum structure: expected array of fields");return{platformFeeRate:BigInt(r[0]),swapFee:BigInt(r[1])}};var k=require("@evolution-sdk/evolution");function F(n){if(n===x)return{unit:x};let t=n.indexOf("."),e=t===-1?n:n.slice(0,t),r=t===-1?"":n.slice(t+1),o=k.Bytes.fromHex(e),i=new k.PolicyId.PolicyId({hash:o}),s=r?k.Bytes.fromHex(r):new Uint8Array(0),a=new k.AssetName.AssetName({bytes:s});return{policyId:i,assetName:a,unit:n}}var nt=n=>{if(!n||Object.keys(n).length===0)return[];let t=[];for(let[e,r]of Object.entries(n)){if(e==="ada")continue;let o=[];for(let[i,s]of Object.entries(r))o.push({name:i,value:s});t.push({policyId:e,assets:o})}return t};var it=(n,t)=>{let e=J,r=1647899091e3,o=328;return t!==1&&(e=K),Math.floor((n-r)/e)+o};function bt(n,t,e,r,o=0n,i){let s=r<0n?-r:r,a=e.tokenX===x?3000000n+BigInt(e.totalSwapFee):0n,m=BigInt(n)-BigInt(e.platformFeeX)+o-a,l=BigInt(t)-BigInt(e.platformFeeY),p=ht(m,l,[BigInt(e.sqrtLowerPriceNum),BigInt(e.sqrtLowerPriceDen)],[BigInt(e.sqrtUpperPriceNum),BigInt(e.sqrtUpperPriceDen)]),I=rt(p[0]*BigInt(e.sqrtUpperPriceDen),p[1]*BigInt(e.sqrtUpperPriceNum))+m,u=rt(p[0]*BigInt(e.sqrtLowerPriceNum),p[1]*BigInt(e.sqrtLowerPriceDen))+l;return r>0n?ot(s,I,u,l,BigInt(e.lpFeeRate),i):ot(s,u,I,m,BigInt(e.lpFeeRate),i)}var ot=(n,t,e,r,o,i)=>{let s=10000n,m=n*o/s*BigInt(i)/10000n,l=s-o,p=t*s+n*l,I=t*e,d=(e*p-I*s)/p;if(d>r)throw new Error("pool out exceeded");return[d,m]},ht=(n,t,e,r)=>{let o=e[1]*r[1],i=e[0]*r[0],s=(t*o-n*i)*(t*o-n*i),a=4n*n*t*e[1]*e[1]*r[0]*r[0],m=Pt(s+a),l=t*o+n*i+m,p=2n*(r[0]*e[1]-r[1]*e[0]);return[l,p]};function Pt(n){if(n<0n)throw new Error("Square root of negative number");if(n<2n)return n;let t=n,e=t+n/t>>1n;for(;e<t;)t=e,e=t+n/t>>1n;return t}function rt(n,t){if(t===0n)throw new Error("Division by zero");let e=n/t;return n%t===0n||n<0n!=t<0n?e:e+1n}function st(n,t){let r=[...t].sort((o,i)=>o.transactionId===i.transactionId?o.index<i.index?-1:1:o.transactionId<i.transactionId?-1:1).findIndex(o=>o.transactionId===n.transactionId&&o.index===n.index);if(r===-1)throw new Error("Protocol config out ref not found in reference inputs");return BigInt(r)}function V(n,t,e){let r=[];for(let o=0;o<n.length;o++){let i=n[o],s=t[o];if(s===0n)continue;let[a,m]=bt(i.tokenAAmount,i.tokenBAmount,i.datum,s,i.rewardAmount||0n,e);r.push({poolIndex:o,deltaAmount:s,outputAmount:a,platformFee:m})}return r}var Q=class{constructor(){}async calculateSwapOut(t,e){if(!t||!t.address)throw new Error("Please connect a wallet first.");let r=(await t.address()).networkId,o=await Promise.all(e.pools.map(u=>t.getUtxosByOutRef([u.poolOutRef]))),i=H(r),s=e.protocolConfigOutRef??i.protocolScriptOutRef,a=(await t.getUtxosByOutRef([s]))[0];if(!a.datumOption)throw new Error("Protocol config UTxO does not contain a datum.");let m=j(a.datumOption),l=await Promise.all(e.pools.map(async(u,d)=>{let A=o[d][0];if(!A.datumOption)throw new Error(`Pool input UTxO ${d} does not contain a datum.`);let y=X(A.datumOption),R=F(y.tokenX),w=F(y.tokenY),O=A.assets.lovelace,g=D=>D.unit===x?O:(0,b.quantityOf)(A.assets,D.policyId,D.assetName),h=null;u.stakingOutRef&&(h=(await t.getUtxosByOutRef([u.stakingOutRef]))[0]);let{rewardAmount:U}=await this.getStakingRewards(t,r,h,R);return{tokenAAmount:g(R),tokenBAmount:g(w),datum:y,rewardAmount:U}})),p=e.pools.map(u=>u.deltaAmount);return V(l,p,m.platformFeeRate).map(u=>u.outputAmount)}async submitSwap(t,e){if(!t||!t.address)throw new Error("Please connect a wallet first.");let r=(await t.address()).networkId,o=await Promise.all(e.pools.map(async c=>(await t.getUtxosByOutRef([c.poolOutRef]))[0])),i=H(r),s=i.poolScriptOutRef,a=e.protocolConfigOutRef??i.protocolScriptOutRef,m=(await t.getUtxosByOutRef([s]))[0],l=(await t.getUtxosByOutRef([a]))[0];if(!l.datumOption)throw new Error("Protocol config UTxO does not contain a datum.");let p=j(l.datumOption),I=[],u=[];for(let c=0;c<e.pools.length;c++){let f=e.pools[c],P=o[c];if(!P.datumOption)throw new Error(`Pool input UTxO ${c} does not contain a datum.`);let T=X(P.datumOption),E=F(T.tokenX),S=F(T.tokenY),$=P.assets.lovelace,_=W=>W.unit===x?$:(0,b.quantityOf)(P.assets,W.policyId,W.assetName),N=null;f.stakingOutRef&&(N=(await t.getUtxosByOutRef([f.stakingOutRef]))[0]),u.push(N);let{rewardAmount:ct}=await this.getStakingRewards(t,r,N,E);I.push({tokenAAmount:_(E),tokenBAmount:_(S),datum:T,rewardAmount:ct,utxo:P,tokenA:E,tokenB:S})}let d=e.pools.map(c=>c.deltaAmount),A=V(I,d,p.platformFeeRate);A.forEach((c,f)=>{let P=e.pools[f].minOutChangeAmount;if(c.outputAmount<P)throw new Error(`Expected swap output at least ${P} but got ${c.outputAmount}`)});let y=A.reduce((c,f)=>c+f.deltaAmount,0n),R=e.pools.find(c=>c.deltaAmount!==0n);if(!R)throw new Error("At least one pool must have a non-zero delta amount");let w=R.deltaAmount>0?I[0].tokenA:I[0].tokenB,O=await this.getUserTokenBalance(t,w);if(O<y)throw new Error(`Insufficient ${w.unit} balance. Required: ${y}, Available: ${O}`);let g=t.newTx(),h=[l];h.push(m),u.forEach(c=>{c&&h.push(c)}),g=g.readFrom({referenceInputs:h});let U=it(Date.now(),r),D=st(l,h);g=g.withdraw({stakeCredential:(0,Y.fromScript)(m.scriptRef),amount:0n,redeemer:v(null,o,d,D)});for(let c=0;c<I.length;c++){let f=I[c],P=A.find(N=>N.poolIndex===c);if(!P)continue;let T=P.deltaAmount,E=P.platformFee,S=et({...f.datum,platformFeeX:BigInt(f.datum.platformFeeX)+(T>0?E:0n),platformFeeY:BigInt(f.datum.platformFeeY)+(T<0?E:0n),lastWithdrawEpoch:U,totalSwapFee:BigInt(f.datum.totalSwapFee)+BigInt(p.swapFee)}),$=this.buildDeltaAssets(T>0?f.tokenA:f.tokenB,T>0?f.tokenB:f.tokenA,T,BigInt(P.outputAmount),BigInt(p.swapFee)),_=(0,b.merge)(f.utxo.assets,$);if(g=g.payToAddress({address:f.utxo.address,assets:_,datum:S}),g=g.collectFrom({inputs:[f.utxo],redeemer:v(f.utxo,o,d,D)}),f.tokenA.unit===x&&U>f.datum.lastWithdrawEpoch&&u[c]){let{stakingRewardAddress:N}=await this.getStakingRewards(t,r,u[c],f.tokenA);N&&(g=g.withdraw({stakeCredential:(0,Y.fromScript)(u[c].scriptRef),amount:f.rewardAmount||0n,redeemer:v(f.utxo,o,d,D)}))}}return g=g.attachMetadata({label:674n,metadata:new Map([["msg",["Danogo Multi-Pool Swap"]]])}),g.setValidity({from:BigInt(Date.now()-12e4),to:BigInt(Date.now()+24e4)}),(await(await(await g.build({scriptDataFormat:"array"})).sign()).submit()).toString()}getPoolsFromOgmiosTx(t,e,r){let o=H(e),i=r??o.poolScriptHash;if(!i)throw new Error("Pool script hash is required but not provided or not found for this network.");let s=[];return t.outputs.forEach((a,m)=>{let l=a.value,p=l[i];if(p&&a.datum){for(let[I,u]of Object.entries(p))if(u===1n){let d=r+I,A=`${t.id}#${m}`,y=l.ada.lovelace,R=nt(l),w=X(a.datum),O=w.tokenX,g=w.tokenY,h=U=>{if(U===x)return y;let D=U.slice(0,56),Z=U.slice(56),M=R.find(c=>c.policyId===D)?.assets.find(c=>c.name===Z);return M?M.value:0n};s.push({outRef:A,address:a.address,coin:y,multiAssets:R,validityNft:d,tokenA:O,tokenAReserve:h(O),tokenB:g,tokenBReserve:h(g),lpFeeRate:w.lpFeeRate,priceLowerNum:w.sqrtLowerPriceNum,priceLowerDen:w.sqrtLowerPriceDen,priceUpperNum:w.sqrtUpperPriceNum,priceUpperDen:w.sqrtUpperPriceDen,platformFeeA:w.platformFeeX,platformFeeB:w.platformFeeY,minAChange:w.minXChange,minBChange:w.minYChange,lpTokenTotalSupply:w.circulatingLPToken,lastWithdrawEpoch:w.lastWithdrawEpoch,totalSwapFee:w.totalSwapFee})}}}),s}async getUserTokenBalance(t,e){return(await t.getWalletUtxos()).reduce((o,i)=>o+(e.unit===x?i.assets.lovelace:(0,b.quantityOf)(i.assets,e.policyId,e.assetName)||0n),0n)}buildDeltaAssets(t,e,r,o,i){let s=r>0n?r:-r,a;if(t.unit===x?a=(0,b.fromLovelace)(s+i):a=(0,b.fromAsset)(t.policyId,t.assetName,s,i),e.unit===x)a=(0,b.subtractLovelace)(a,o);else{let m=(0,b.fromAsset)(e.policyId,e.assetName,-o);a=(0,b.merge)(a,m)}return a}async getStakingRewards(t,e,r,o){if(o.unit!==x)return{rewardAmount:0n};let i=new z.RewardAccount.RewardAccount({networkId:e,stakeCredential:(0,Y.fromScript)(r.scriptRef)}),s=z.RewardAccount.toBech32(i);return{rewardAmount:(await t.getDelegation(s)).rewards,stakingRewardAddress:s}}},Rt=Q;
|
package/dist/sdk.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{RewardAccount as j}from"@evolution-sdk/evolution";import{fromScript as N}from"@evolution-sdk/evolution/ScriptHash";import{fromAsset as V,merge as G,quantityOf as v,fromLovelace as rt,subtractLovelace as it}from"@evolution-sdk/evolution/Assets";import{Data as K}from"@evolution-sdk/evolution";function A(n,e){let r=(n>=0n?n:n+(1n<<256n)).toString(16);r.length%2&&(r="0"+r);let o=r.length/2;if(o>e)throw new Error(`Number ${n} requires ${o} bytes, but target length is ${e}.`);let s=new Uint8Array(e),i=e-o;for(let a=0;a<o;a++)s[a+i]=parseInt(r.slice(a*2,a*2+2),16);return s}var D=(n,e,t,r)=>{try{let o=s=>{let i=3n,a=A(r?t:s,1),g=A(s,1),l=A(i,1),u=A(0n,1),f=A(e[0],32),d=a.length+l.length+g.length+u.length+f.length,m=new Uint8Array(d),c=0;m.set(a,c),c+=a.length,m.set(l,c),c+=l.length,m.set(g,c),c+=g.length,m.set(u,c),c+=u.length,m.set(f,c);let w=Buffer.from(m).toString("hex");return K.fromCBORHex("5824"+w)};return{all:s=>{if(!s.length)throw new Error("swapTokensRedeemer batch all called with empty indexedInputs");let i=BigInt(s[0].index);return o(i)},inputs:n}}catch(o){throw console.error("Error creating pool redeemer:",o),o}};import{Data as B,CBOR as T}from"@evolution-sdk/evolution";import{InlineDatum as Z}from"@evolution-sdk/evolution/InlineDatum";var X=n=>{let e=[new Uint8Array(Buffer.from(n.tokenX.slice(0,56),"hex")),new Uint8Array(Buffer.from(n.tokenX.slice(57),"hex"))],t=[new Uint8Array(Buffer.from(n.tokenY.slice(0,56),"hex")),new Uint8Array(Buffer.from(n.tokenY.slice(57),"hex"))],r=B.constr(0n,[n.sqrtLowerPriceNum,n.sqrtLowerPriceDen]),o=B.constr(0n,[n.sqrtUpperPriceNum,n.sqrtUpperPriceDen]),s=B.constr(0n,[e,t,BigInt(n.lpFeeRate),n.platformFeeX,n.platformFeeY,n.totalSwapFee,r,o,n.minXChange,n.minYChange,n.circulatingLPToken,BigInt(n.lastWithdrawEpoch)]);return new Z({data:s})};var U=n=>{let e;if(typeof n=="string")e=T.fromCBORHex(n);else{let s=n.data,i=B.toCBORHex(s);e=T.fromCBORHex(i)}let t=e._tag==="Tag"?e.value:e;if(!Array.isArray(t))throw new Error("Invalid datum structure: expected array of fields");let r=s=>{let i=s._tag==="Tag"?s.value:s;if(Array.isArray(i)&&i.length===2){let a=i[0]instanceof Uint8Array?i[0]:new Uint8Array(i[0]),g=i[1]instanceof Uint8Array?i[1]:new Uint8Array(i[1]),l=Buffer.from(a).toString("hex"),u=Buffer.from(g).toString("hex");return l===""&&u===""?"lovelace":l+"."+u}throw new Error("Invalid AssetClass structure")},o=s=>{let i=s._tag==="Tag"?s.value:s;if(Array.isArray(i)&&i.length===2)return{num:BigInt(i[0]),den:BigInt(i[1])};throw new Error("Invalid Ratio structure")};return{tokenX:r(t[0]),tokenY:r(t[1]),lpFeeRate:Number(t[2]),platformFeeX:BigInt(t[3]),platformFeeY:BigInt(t[4]),totalSwapFee:BigInt(t[5]),sqrtLowerPriceNum:o(t[6]).num,sqrtLowerPriceDen:o(t[6]).den,sqrtUpperPriceNum:o(t[7]).num,sqrtUpperPriceDen:o(t[7]).den,minXChange:BigInt(t[8]),minYChange:BigInt(t[9]),circulatingLPToken:BigInt(t[10]),lastWithdrawEpoch:Number(t[11])}},F=n=>{let e,t=B.toCBORHex(n.data);e=T.fromCBORHex(t);let r=e._tag==="Tag"?e.value:e;if(!Array.isArray(r))throw new Error("Invalid datum structure: expected array of fields");return{platformFeeRate:BigInt(r[0]),swapFee:BigInt(r[1])}};import{AssetName as tt,Bytes as Y,PolicyId as et}from"@evolution-sdk/evolution";function b(n){if(n==="lovelace")return{unit:"lovelace"};let e=n.indexOf("."),t=e===-1?n:n.slice(0,e),r=e===-1?"":n.slice(e+1),o=Y.fromHex(t),s=new et.PolicyId({hash:o}),i=r?Y.fromHex(r):new Uint8Array(0),a=new tt.AssetName({bytes:i});return{policyId:s,assetName:a,unit:n}}var H=n=>{if(!n||Object.keys(n).length===0)return[];let e=[];for(let[t,r]of Object.entries(n)){if(t==="ada")continue;let o=[];for(let[s,i]of Object.entries(r))o.push({name:s,value:i});e.push({policyId:t,assets:o})}return e};var _=(n,e)=>{let t=432e6,r=1647899091e3,o=328;return e!==1&&(t=18e5),Math.floor((n-r)/t)+o};function C(n,e,t,r,o=0n,s){let i=r<0n?-r:r,a=t.tokenX==="lovelace"?3000000n+BigInt(t.totalSwapFee):0n,g=BigInt(n)-BigInt(t.platformFeeX)+o-a,l=BigInt(e)-BigInt(t.platformFeeY),u=nt(g,l,[BigInt(t.sqrtLowerPriceNum),BigInt(t.sqrtLowerPriceDen)],[BigInt(t.sqrtUpperPriceNum),BigInt(t.sqrtUpperPriceDen)]),f=M(u[0]*BigInt(t.sqrtUpperPriceDen),u[1]*BigInt(t.sqrtUpperPriceNum))+g,d=M(u[0]*BigInt(t.sqrtLowerPriceNum),u[1]*BigInt(t.sqrtLowerPriceDen))+l;return r>0n?$(i,f,d,l,BigInt(t.lpFeeRate),s):$(i,d,f,g,BigInt(t.lpFeeRate),s)}var $=(n,e,t,r,o,s)=>{let i=10000n,g=n*o/i*BigInt(s)/10000n,l=i-o,u=e*i+n*l,f=e*t,m=(t*u-f*i)/u;if(m>r)throw new Error("pool out exceeded");return[m,g]},nt=(n,e,t,r)=>{let o=t[1]*r[1],s=t[0]*r[0],i=(e*o-n*s)*(e*o-n*s),a=4n*n*e*t[1]*t[1]*r[0]*r[0],g=ot(i+a),l=e*o+n*s+g,u=2n*(r[0]*t[1]-r[1]*t[0]);return[l,u]};function ot(n){if(n<0n)throw new Error("Square root of negative number");if(n<2n)return n;let e=n,t=e+n/e>>1n;for(;t<e;)e=t,t=e+n/e>>1n;return e}function M(n,e){if(e===0n)throw new Error("Division by zero");let t=n/e;return n%e===0n||n<0n!=e<0n?t:t+1n}function W(n,e){let r=[...e].sort((o,s)=>o.transactionId===s.transactionId?o.index<s.index?-1:1:o.transactionId<s.transactionId?-1:1).findIndex(o=>o.transactionId===n.transactionId&&o.index===n.index);if(r===-1)throw new Error("Protocol config out ref not found in reference inputs");return BigInt(r)}var S=class{constructor(){}async calculateSwapOut(e,t){if(!e||!e.address)throw new Error("Please connect a wallet first.");let r=(await e.address()).networkId,o=(await e.getUtxosByOutRef([t.poolOutRef]))[0],s=null;if(t.stakingOutRef&&(s=(await e.getUtxosByOutRef([t.stakingOutRef]))[0]),!o.datumOption)throw new Error("Pool input UTxO does not contain a datum.");let i=(await e.getUtxosByOutRef([t.protocolConfigOutRef]))[0];if(!i.datumOption)throw new Error("Protocol config UTxO does not contain a datum.");let a=F(i.datumOption),g=U(o.datumOption),l=b(g.tokenX),u=b(g.tokenY),f=o.assets.lovelace,d=y=>y.unit==="lovelace"?f:v(o.assets,y.policyId,y.assetName),{rewardAmount:m}=await this.getStakingRewards(e,r,s,l),[c,w]=C(d(l),d(u),g,t.deltaAmount,m,a.platformFeeRate);return c}async submitSwap(e,t){if(!e||!e.address)throw new Error("Please connect a wallet first.");let r=(await e.address()).networkId,o=(await e.getUtxosByOutRef([t.poolOutRef]))[0],s=(await e.getUtxosByOutRef([t.poolScriptOutRef]))[0],i=null;if(t.stakingOutRef&&(i=(await e.getUtxosByOutRef([t.stakingOutRef]))[0]),!o.datumOption)throw new Error("Pool input UTxO does not contain a datum.");let a=(await e.getUtxosByOutRef([t.protocolConfigOutRef]))[0];if(!a.datumOption)throw new Error("Protocol config UTxO does not contain a datum.");let g=F(a.datumOption),l=U(o.datumOption),u=b(l.tokenX),f=b(l.tokenY),d=o.assets.lovelace,m=k=>k.unit==="lovelace"?d:v(o.assets,k.policyId,k.assetName),c=t.deltaAmount,w=c>0?u:f,y=c>0?f:u,p=e.newTx(),I=await this.getUserTokenBalance(e,w),P=c<0n?-c:c;if(I<P)throw new Error(`Insufficient ${w.unit} balance. Required: ${P}, Available: ${I}`);p=p.readFrom({referenceInputs:[s,a]}),i&&(p=p.readFrom({referenceInputs:[i]}));let{rewardAmount:R,stakingRewardAddress:E}=await this.getStakingRewards(e,r,i,u),[h,x]=C(m(u),m(f),l,c,R,g.platformFeeRate);if(h<t.minOutChangeAmount)throw new Error(`Slippage too high. Expected at least ${t.minOutChangeAmount} but got ${h}`);let q=_(Date.now(),r),Q=X({...l,platformFeeX:BigInt(l.platformFeeX)+(w.unit===u.unit?x:0n),platformFeeY:BigInt(l.platformFeeY)+(w.unit===f.unit?x:0n),lastWithdrawEpoch:q,totalSwapFee:BigInt(l.totalSwapFee)+BigInt(g.swapFee)}),z=this.buildDeltaAssets(w,y,c,BigInt(h),BigInt(g.swapFee)),J=G(o.assets,z);p=p.payToAddress({address:o.address,assets:J,datum:Q}),p=p.attachMetadata({label:674n,metadata:new Map([["msg",["Danogo Liquidity Pair: Swap"]]])});let L=[s,a];i&&L.push(i);let O=W(a,L);return p=p.collectFrom({inputs:[o],redeemer:D([o],[c],O,!1)}),p=p.withdraw({stakeCredential:N(s.scriptRef),amount:0n,redeemer:D([o],[c],O,!0)}),u.unit==="lovelace"&&q>l.lastWithdrawEpoch&&E&&(p=p.withdraw({stakeCredential:N(i.scriptRef),amount:R,redeemer:D([o],[c],O,!1)})),p.setValidity({from:BigInt(Date.now()-12e4),to:BigInt(Date.now()+24e4)}),(await(await(await p.build({debug:!0})).sign()).submit()).toString()}getPoolsFromOgmiosTx(e,t){let r=[];return e.outputs.forEach((o,s)=>{let i=o.value,a=i[t];if(a&&o.datum){for(let[g,l]of Object.entries(a))if(l===1n){let u=t+g,f=`${e.id}#${s}`,d=i.ada.lovelace,m=H(i),c=U(o.datum),w=c.tokenX,y=c.tokenY,p=I=>{if(I==="lovelace"||I==="")return d;let P=I.slice(0,56),R=I.slice(56),h=m.find(x=>x.policyId===P)?.assets.find(x=>x.name===R);return h?h.value:0n};r.push({outRef:f,address:o.address,coin:d,multiAssets:m,validityNft:u,tokenA:w,tokenAReserve:p(w),tokenB:y,tokenBReserve:p(y),lpFeeRate:c.lpFeeRate,priceLowerNum:c.sqrtLowerPriceNum,priceLowerDen:c.sqrtLowerPriceDen,priceUpperNum:c.sqrtUpperPriceNum,priceUpperDen:c.sqrtUpperPriceDen,platformFeeA:c.platformFeeX,platformFeeB:c.platformFeeY,minAChange:c.minXChange,minBChange:c.minYChange,lpTokenTotalSupply:c.circulatingLPToken,lastWithdrawEpoch:c.lastWithdrawEpoch,totalSwapFee:c.totalSwapFee})}}}),r}async getUserTokenBalance(e,t){return(await e.getWalletUtxos()).reduce((o,s)=>o+(t.unit==="lovelace"?s.assets.lovelace:v(s.assets,t.policyId,t.assetName)||0n),0n)}buildDeltaAssets(e,t,r,o,s){let i=r>0n?r:-r,a;if(e.unit==="lovelace"?a=rt(i+s):a=V(e.policyId,e.assetName,i,s),t.unit==="lovelace")a=it(a,o);else{let g=V(t.policyId,t.assetName,-o);a=G(a,g)}return a}async getStakingRewards(e,t,r,o){if(o.unit!=="lovelace")return{rewardAmount:0n};let s=new j.RewardAccount({networkId:t,stakeCredential:N(r.scriptRef)}),i=j.toBech32(s);return{rewardAmount:(await e.getDelegation(i)).rewards,stakingRewardAddress:i}}},kt=S;export{kt as default};
|
|
1
|
+
import{RewardAccount as rt}from"@evolution-sdk/evolution";import{fromScript as W}from"@evolution-sdk/evolution/ScriptHash";import{fromAsset as it,merge as st,quantityOf as G,fromLovelace as Pt,subtractLovelace as Rt}from"@evolution-sdk/evolution/Assets";function N(n,e){let o=(n>=0n?n:n+(1n<<256n)).toString(16);o.length%2&&(o="0"+o);let r=o.length/2;if(r>e)throw new Error(`Number ${n} requires ${r} bytes, but target length is ${e}.`);let i=new Uint8Array(e),s=e-r;for(let a=0;a<r;a++)i[a+s]=parseInt(o.slice(a*2,a*2+2),16);return i}var S=(n,e,t,o)=>{try{let r=(i,s)=>{let a=3n,m=N(n?i:o,1),l=N(a,1),p=e.map((A,y)=>{let P=s.find(b=>b.utxo.transactionId===A.transactionId&&b.utxo.index===A.index);if(!P)throw new Error(`Pool UTxO at ${y} not found in indexedInputs`);if(t[y]===void 0)throw new Error(`deltaAmount for poolOutIdx ${y} is undefined`);let w=N(BigInt(P.index),1),R=N(BigInt(y),1),g=N(t[y],32);return{poolInBytes:w,poolOutBytes:R,amountBytes:g}}),I=2+34*p.length,u=new Uint8Array(I),d=0;u.set(m,d),d+=m.length,u.set(l,d),d+=l.length;for(let A of p)u.set(A.poolInBytes,d),d+=A.poolInBytes.length,u.set(A.poolOutBytes,d),d+=A.poolOutBytes.length,u.set(A.amountBytes,d),d+=A.amountBytes.length;return u};return{all:i=>{if(!i.length)throw new Error("swapTokensRedeemer batch all called with empty indexedInputs");let s=null;if(n&&(s=i.find(a=>a.utxo.transactionId===n.transactionId&&a.utxo.index===n.index),!s))throw new Error("Target pool UTxO is not found in poolInUTxOs");return r(s?.index,i)},inputs:e}}catch(r){throw console.error("Error creating pool redeemer:",r),r}};import{Data as k,CBOR as Y}from"@evolution-sdk/evolution";import{InlineDatum as At}from"@evolution-sdk/evolution/InlineDatum";import{TransactionHash as ut,TransactionInput as lt}from"@evolution-sdk/evolution";var x="lovelace",z=432e6,pt="64d111b957e7d7848ffdde5149aa77fa4090a7fa1ad0ac108067900614848501#0",ft="d8b69fc53637bcfadbc4469083f706bc293f4d9d2296646c5ca167bb",mt="2cafd7c92f7093e5229af274be83dea660b0590b4174bbed79ba662b44fbd1ee#0",Q=18e5,dt="2e19cca74e3badcab26aef7574aa1885ba97228a254ca227ba2f79f2b75fd136#0",gt="04041c3c6ba87b33f2c9eb7f7dbeae3b26003c3e199d438bb99932a2",wt="3775af36f485f9c97101ee5b9b360c34f0f8e12186bc9060f358b7fc8ce468a4#0",v=n=>n===1?{poolScriptOutRef:_(pt),poolScriptHash:ft,protocolScriptOutRef:_(mt)}:{poolScriptOutRef:_(dt),poolScriptHash:gt,protocolScriptOutRef:_(wt)},_=n=>{if(!n)return;let[e,t]=n.split("#");return new lt.TransactionInput({transactionId:ut.fromHex(e),index:BigInt(t)})};var Z=n=>{let e=[new Uint8Array(Buffer.from(n.tokenX.slice(0,56),"hex")),new Uint8Array(Buffer.from(n.tokenX.slice(57),"hex"))],t=[new Uint8Array(Buffer.from(n.tokenY.slice(0,56),"hex")),new Uint8Array(Buffer.from(n.tokenY.slice(57),"hex"))],o=k.constr(0n,[n.sqrtLowerPriceNum,n.sqrtLowerPriceDen]),r=k.constr(0n,[n.sqrtUpperPriceNum,n.sqrtUpperPriceDen]),i=k.constr(0n,[e,t,BigInt(n.lpFeeRate),n.platformFeeX,n.platformFeeY,n.totalSwapFee,o,r,n.minXChange,n.minYChange,n.circulatingLPToken,BigInt(n.lastWithdrawEpoch)]);return new At({data:i})};var q=n=>{let e;if(typeof n=="string")e=Y.fromCBORHex(n);else{let i=n.data,s=k.toCBORHex(i);e=Y.fromCBORHex(s)}let t=e._tag==="Tag"?e.value:e;if(!Array.isArray(t))throw new Error("Invalid datum structure: expected array of fields");let o=i=>{let s=i._tag==="Tag"?i.value:i;if(Array.isArray(s)&&s.length===2){let a=s[0]instanceof Uint8Array?s[0]:new Uint8Array(s[0]),m=s[1]instanceof Uint8Array?s[1]:new Uint8Array(s[1]),l=Buffer.from(a).toString("hex"),p=Buffer.from(m).toString("hex");return l===""&&p===""?x:l+"."+p}throw new Error("Invalid AssetClass structure")},r=i=>{let s=i._tag==="Tag"?i.value:i;if(Array.isArray(s)&&s.length===2)return{num:BigInt(s[0]),den:BigInt(s[1])};throw new Error("Invalid Ratio structure")};return{tokenX:o(t[0]),tokenY:o(t[1]),lpFeeRate:Number(t[2]),platformFeeX:BigInt(t[3]),platformFeeY:BigInt(t[4]),totalSwapFee:BigInt(t[5]),sqrtLowerPriceNum:r(t[6]).num,sqrtLowerPriceDen:r(t[6]).den,sqrtUpperPriceNum:r(t[7]).num,sqrtUpperPriceDen:r(t[7]).den,minXChange:BigInt(t[8]),minYChange:BigInt(t[9]),circulatingLPToken:BigInt(t[10]),lastWithdrawEpoch:Number(t[11])}},M=n=>{let e,t=k.toCBORHex(n.data);e=Y.fromCBORHex(t);let o=e._tag==="Tag"?e.value:e;if(!Array.isArray(o))throw new Error("Invalid datum structure: expected array of fields");return{platformFeeRate:BigInt(o[0]),swapFee:BigInt(o[1])}};import{AssetName as It,Bytes as J,PolicyId as xt}from"@evolution-sdk/evolution";function E(n){if(n===x)return{unit:x};let e=n.indexOf("."),t=e===-1?n:n.slice(0,e),o=e===-1?"":n.slice(e+1),r=J.fromHex(t),i=new xt.PolicyId({hash:r}),s=o?J.fromHex(o):new Uint8Array(0),a=new It.AssetName({bytes:s});return{policyId:i,assetName:a,unit:n}}var K=n=>{if(!n||Object.keys(n).length===0)return[];let e=[];for(let[t,o]of Object.entries(n)){if(t==="ada")continue;let r=[];for(let[i,s]of Object.entries(o))r.push({name:i,value:s});e.push({policyId:t,assets:r})}return e};var nt=(n,e)=>{let t=z,o=1647899091e3,r=328;return e!==1&&(t=Q),Math.floor((n-o)/t)+r};function yt(n,e,t,o,r=0n,i){let s=o<0n?-o:o,a=t.tokenX===x?3000000n+BigInt(t.totalSwapFee):0n,m=BigInt(n)-BigInt(t.platformFeeX)+r-a,l=BigInt(e)-BigInt(t.platformFeeY),p=bt(m,l,[BigInt(t.sqrtLowerPriceNum),BigInt(t.sqrtLowerPriceDen)],[BigInt(t.sqrtUpperPriceNum),BigInt(t.sqrtUpperPriceDen)]),I=et(p[0]*BigInt(t.sqrtUpperPriceDen),p[1]*BigInt(t.sqrtUpperPriceNum))+m,u=et(p[0]*BigInt(t.sqrtLowerPriceNum),p[1]*BigInt(t.sqrtLowerPriceDen))+l;return o>0n?tt(s,I,u,l,BigInt(t.lpFeeRate),i):tt(s,u,I,m,BigInt(t.lpFeeRate),i)}var tt=(n,e,t,o,r,i)=>{let s=10000n,m=n*r/s*BigInt(i)/10000n,l=s-r,p=e*s+n*l,I=e*t,d=(t*p-I*s)/p;if(d>o)throw new Error("pool out exceeded");return[d,m]},bt=(n,e,t,o)=>{let r=t[1]*o[1],i=t[0]*o[0],s=(e*r-n*i)*(e*r-n*i),a=4n*n*e*t[1]*t[1]*o[0]*o[0],m=ht(s+a),l=e*r+n*i+m,p=2n*(o[0]*t[1]-o[1]*t[0]);return[l,p]};function ht(n){if(n<0n)throw new Error("Square root of negative number");if(n<2n)return n;let e=n,t=e+n/e>>1n;for(;t<e;)e=t,t=e+n/e>>1n;return e}function et(n,e){if(e===0n)throw new Error("Division by zero");let t=n/e;return n%e===0n||n<0n!=e<0n?t:t+1n}function ot(n,e){let o=[...e].sort((r,i)=>r.transactionId===i.transactionId?r.index<i.index?-1:1:r.transactionId<i.transactionId?-1:1).findIndex(r=>r.transactionId===n.transactionId&&r.index===n.index);if(o===-1)throw new Error("Protocol config out ref not found in reference inputs");return BigInt(o)}function $(n,e,t){let o=[];for(let r=0;r<n.length;r++){let i=n[r],s=e[r];if(s===0n)continue;let[a,m]=yt(i.tokenAAmount,i.tokenBAmount,i.datum,s,i.rewardAmount||0n,t);o.push({poolIndex:r,deltaAmount:s,outputAmount:a,platformFee:m})}return o}var j=class{constructor(){}async calculateSwapOut(e,t){if(!e||!e.address)throw new Error("Please connect a wallet first.");let o=(await e.address()).networkId,r=await Promise.all(t.pools.map(u=>e.getUtxosByOutRef([u.poolOutRef]))),i=v(o),s=t.protocolConfigOutRef??i.protocolScriptOutRef,a=(await e.getUtxosByOutRef([s]))[0];if(!a.datumOption)throw new Error("Protocol config UTxO does not contain a datum.");let m=M(a.datumOption),l=await Promise.all(t.pools.map(async(u,d)=>{let A=r[d][0];if(!A.datumOption)throw new Error(`Pool input UTxO ${d} does not contain a datum.`);let y=q(A.datumOption),P=E(y.tokenX),w=E(y.tokenY),R=A.assets.lovelace,g=B=>B.unit===x?R:G(A.assets,B.policyId,B.assetName),b=null;u.stakingOutRef&&(b=(await e.getUtxosByOutRef([u.stakingOutRef]))[0]);let{rewardAmount:D}=await this.getStakingRewards(e,o,b,P);return{tokenAAmount:g(P),tokenBAmount:g(w),datum:y,rewardAmount:D}})),p=t.pools.map(u=>u.deltaAmount);return $(l,p,m.platformFeeRate).map(u=>u.outputAmount)}async submitSwap(e,t){if(!e||!e.address)throw new Error("Please connect a wallet first.");let o=(await e.address()).networkId,r=await Promise.all(t.pools.map(async c=>(await e.getUtxosByOutRef([c.poolOutRef]))[0])),i=v(o),s=i.poolScriptOutRef,a=t.protocolConfigOutRef??i.protocolScriptOutRef,m=(await e.getUtxosByOutRef([s]))[0],l=(await e.getUtxosByOutRef([a]))[0];if(!l.datumOption)throw new Error("Protocol config UTxO does not contain a datum.");let p=M(l.datumOption),I=[],u=[];for(let c=0;c<t.pools.length;c++){let f=t.pools[c],h=r[c];if(!h.datumOption)throw new Error(`Pool input UTxO ${c} does not contain a datum.`);let O=q(h.datumOption),U=E(O.tokenX),C=E(O.tokenY),H=h.assets.lovelace,F=X=>X.unit===x?H:G(h.assets,X.policyId,X.assetName),T=null;f.stakingOutRef&&(T=(await e.getUtxosByOutRef([f.stakingOutRef]))[0]),u.push(T);let{rewardAmount:ct}=await this.getStakingRewards(e,o,T,U);I.push({tokenAAmount:F(U),tokenBAmount:F(C),datum:O,rewardAmount:ct,utxo:h,tokenA:U,tokenB:C})}let d=t.pools.map(c=>c.deltaAmount),A=$(I,d,p.platformFeeRate);A.forEach((c,f)=>{let h=t.pools[f].minOutChangeAmount;if(c.outputAmount<h)throw new Error(`Expected swap output at least ${h} but got ${c.outputAmount}`)});let y=A.reduce((c,f)=>c+f.deltaAmount,0n),P=t.pools.find(c=>c.deltaAmount!==0n);if(!P)throw new Error("At least one pool must have a non-zero delta amount");let w=P.deltaAmount>0?I[0].tokenA:I[0].tokenB,R=await this.getUserTokenBalance(e,w);if(R<y)throw new Error(`Insufficient ${w.unit} balance. Required: ${y}, Available: ${R}`);let g=e.newTx(),b=[l];b.push(m),u.forEach(c=>{c&&b.push(c)}),g=g.readFrom({referenceInputs:b});let D=nt(Date.now(),o),B=ot(l,b);g=g.withdraw({stakeCredential:W(m.scriptRef),amount:0n,redeemer:S(null,r,d,B)});for(let c=0;c<I.length;c++){let f=I[c],h=A.find(T=>T.poolIndex===c);if(!h)continue;let O=h.deltaAmount,U=h.platformFee,C=Z({...f.datum,platformFeeX:BigInt(f.datum.platformFeeX)+(O>0?U:0n),platformFeeY:BigInt(f.datum.platformFeeY)+(O<0?U:0n),lastWithdrawEpoch:D,totalSwapFee:BigInt(f.datum.totalSwapFee)+BigInt(p.swapFee)}),H=this.buildDeltaAssets(O>0?f.tokenA:f.tokenB,O>0?f.tokenB:f.tokenA,O,BigInt(h.outputAmount),BigInt(p.swapFee)),F=st(f.utxo.assets,H);if(g=g.payToAddress({address:f.utxo.address,assets:F,datum:C}),g=g.collectFrom({inputs:[f.utxo],redeemer:S(f.utxo,r,d,B)}),f.tokenA.unit===x&&D>f.datum.lastWithdrawEpoch&&u[c]){let{stakingRewardAddress:T}=await this.getStakingRewards(e,o,u[c],f.tokenA);T&&(g=g.withdraw({stakeCredential:W(u[c].scriptRef),amount:f.rewardAmount||0n,redeemer:S(f.utxo,r,d,B)}))}}return g=g.attachMetadata({label:674n,metadata:new Map([["msg",["Danogo Multi-Pool Swap"]]])}),g.setValidity({from:BigInt(Date.now()-12e4),to:BigInt(Date.now()+24e4)}),(await(await(await g.build({scriptDataFormat:"array"})).sign()).submit()).toString()}getPoolsFromOgmiosTx(e,t,o){let r=v(t),i=o??r.poolScriptHash;if(!i)throw new Error("Pool script hash is required but not provided or not found for this network.");let s=[];return e.outputs.forEach((a,m)=>{let l=a.value,p=l[i];if(p&&a.datum){for(let[I,u]of Object.entries(p))if(u===1n){let d=o+I,A=`${e.id}#${m}`,y=l.ada.lovelace,P=K(l),w=q(a.datum),R=w.tokenX,g=w.tokenY,b=D=>{if(D===x)return y;let B=D.slice(0,56),V=D.slice(56),L=P.find(c=>c.policyId===B)?.assets.find(c=>c.name===V);return L?L.value:0n};s.push({outRef:A,address:a.address,coin:y,multiAssets:P,validityNft:d,tokenA:R,tokenAReserve:b(R),tokenB:g,tokenBReserve:b(g),lpFeeRate:w.lpFeeRate,priceLowerNum:w.sqrtLowerPriceNum,priceLowerDen:w.sqrtLowerPriceDen,priceUpperNum:w.sqrtUpperPriceNum,priceUpperDen:w.sqrtUpperPriceDen,platformFeeA:w.platformFeeX,platformFeeB:w.platformFeeY,minAChange:w.minXChange,minBChange:w.minYChange,lpTokenTotalSupply:w.circulatingLPToken,lastWithdrawEpoch:w.lastWithdrawEpoch,totalSwapFee:w.totalSwapFee})}}}),s}async getUserTokenBalance(e,t){return(await e.getWalletUtxos()).reduce((r,i)=>r+(t.unit===x?i.assets.lovelace:G(i.assets,t.policyId,t.assetName)||0n),0n)}buildDeltaAssets(e,t,o,r,i){let s=o>0n?o:-o,a;if(e.unit===x?a=Pt(s+i):a=it(e.policyId,e.assetName,s,i),t.unit===x)a=Rt(a,r);else{let m=it(t.policyId,t.assetName,-r);a=st(a,m)}return a}async getStakingRewards(e,t,o,r){if(r.unit!==x)return{rewardAmount:0n};let i=new rt.RewardAccount({networkId:t,stakeCredential:W(o.scriptRef)}),s=rt.toBech32(i);return{rewardAmount:(await e.getDelegation(s)).rewards,stakingRewardAddress:s}}},Qt=j;export{Qt as default};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "danogo-clmm",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "An SDK to calculate and execute swaps on the Danogo liquidity platform.",
|
|
5
5
|
"main": "./dist/sdk.js",
|
|
6
6
|
"module": "./dist/sdk.mjs",
|
|
@@ -33,12 +33,12 @@
|
|
|
33
33
|
"access": "public"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@cardano-ogmios/client": "
|
|
37
|
-
"@cardano-ogmios/schema": "
|
|
38
|
-
"@evolution-sdk/evolution": "
|
|
36
|
+
"@cardano-ogmios/client": "6.14.0",
|
|
37
|
+
"@cardano-ogmios/schema": "6.14.0",
|
|
38
|
+
"@evolution-sdk/evolution": "0.3.32"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"tsup": "^8.0.0",
|
|
42
42
|
"typescript": "^5.9.2"
|
|
43
43
|
}
|
|
44
|
-
}
|
|
44
|
+
}
|