danogo-clmm 0.0.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 +178 -0
- package/dist/sdk.d.mts +97 -0
- package/dist/sdk.d.ts +97 -0
- package/dist/sdk.js +1 -0
- package/dist/sdk.mjs +1 -0
- package/package.json +30 -0
package/README.md
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# Danogo Swap SDK
|
|
2
|
+
|
|
3
|
+
An SDK to calculate and execute swaps on the Danogo liquidity platform on the Cardano network.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install danogo-clmm-sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
### Prerequisites
|
|
14
|
+
|
|
15
|
+
This SDK relies on `@lucid-evolution/lucid` for wallet management and transaction building.
|
|
16
|
+
|
|
17
|
+
### Initialization
|
|
18
|
+
|
|
19
|
+
Initialize the SDK with the Danogo API URL. Optionally, you can provide a custom pool script hash.
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import DanogoSwap from "danogo-clmm-sdk";
|
|
23
|
+
|
|
24
|
+
const sdk = new DanogoSwap();
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### 1. Calculate Swap Output (Quote)
|
|
28
|
+
|
|
29
|
+
Calculate the expected output of a swap without submitting a transaction. This is useful for UI previews or checking rates.
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
import DanogoSwap from "danogo-clmm-sdk";
|
|
33
|
+
import { Lucid, Kupmios } from "@lucid-evolution/lucid";
|
|
34
|
+
|
|
35
|
+
const sdk = new DanogoSwap();
|
|
36
|
+
|
|
37
|
+
async function main() {
|
|
38
|
+
const lucid = await Lucid(
|
|
39
|
+
new Kupmios("kupo_url", "ogmios_url"),
|
|
40
|
+
"Preprod"
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
const quoteRequest = {
|
|
44
|
+
poolOutRef: {
|
|
45
|
+
txHash:
|
|
46
|
+
"your_tx_hash",
|
|
47
|
+
outputIndex: 0, // your output index
|
|
48
|
+
},
|
|
49
|
+
stakingOutRef: {
|
|
50
|
+
txHash:
|
|
51
|
+
"your_tx_hash",
|
|
52
|
+
outputIndex: 1, // your output index
|
|
53
|
+
},
|
|
54
|
+
deltaAmount: -3000000n,
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
const expectedOutput = await sdk.calculateSwapOut(lucid, quoteRequest);
|
|
59
|
+
console.log(`Expected output amount: ${expectedOutput}`);
|
|
60
|
+
} catch (error) {
|
|
61
|
+
console.error("Calculation failed", error);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 2. Submit Swap Transaction
|
|
67
|
+
|
|
68
|
+
Build and submit a swap transaction using a Lucid instance.
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
import DanogoSwap from "danogo-clmm-sdk";
|
|
72
|
+
import { Lucid, Kupmios } from "@lucid-evolution/lucid";
|
|
73
|
+
|
|
74
|
+
const sdk = new DanogoSwap();
|
|
75
|
+
|
|
76
|
+
async function main() {
|
|
77
|
+
// 1. Initialize Lucid with your provider (recommend Kupmios)
|
|
78
|
+
const lucid = await Lucid(
|
|
79
|
+
new Kupmios("kupo_url", "ogmios_url"),
|
|
80
|
+
"Preprod"
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
// 2. Select wallet
|
|
84
|
+
lucid.selectWallet.fromSeed("your seed phrase");
|
|
85
|
+
|
|
86
|
+
const swapRequest = {
|
|
87
|
+
poolOutRef: {
|
|
88
|
+
txHash:
|
|
89
|
+
"your_tx_hash",
|
|
90
|
+
outputIndex: 0, // your pool output index
|
|
91
|
+
},
|
|
92
|
+
poolScriptOutRef: {
|
|
93
|
+
txHash:
|
|
94
|
+
"your_tx_hash",
|
|
95
|
+
outputIndex: 0, // your pool script output index
|
|
96
|
+
},
|
|
97
|
+
stakingOutRef: {
|
|
98
|
+
txHash:
|
|
99
|
+
"your_tx_hash",
|
|
100
|
+
outputIndex: 1, // your staking output index
|
|
101
|
+
},
|
|
102
|
+
deltaAmount: -3000000n, // Positive: User sells X -> Buy Y, Negative: User sells Y -> Buy X
|
|
103
|
+
minOutChangeAmount: 10000n, // Minimum amount of token received to accept
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
try {
|
|
107
|
+
const txHash = await sdk.submitSwap(lucid, swapRequest);
|
|
108
|
+
console.log(`Transaction submitted: ${txHash}`);
|
|
109
|
+
} catch (error) {
|
|
110
|
+
console.error("Swap failed", error);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Note for Kupmios Users: There is currently a known issue with lucid-evolution when using Kupmios for transaction evaluation. If you encounter errors during submission, you may need to manually patch node_modules/@lucid-evolution/provider/dist/index.js node_modules/@lucid-evolution/provider/dist/index.cjs by commenting out the additionalUtxo line in the evaluateTx method:
|
|
116
|
+
```javascript
|
|
117
|
+
const data = {
|
|
118
|
+
jsonrpc: "2.0",
|
|
119
|
+
method: "evaluateTransaction",
|
|
120
|
+
params: {
|
|
121
|
+
transaction: { cbor: tx },
|
|
122
|
+
// additionalUtxo: toOgmiosUTxOs(additionalUTxOs) // comment here
|
|
123
|
+
},
|
|
124
|
+
id: null
|
|
125
|
+
};
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
### 3. Get Pool Info from Ogmios Transaction
|
|
130
|
+
|
|
131
|
+
Extract pool data directly from an Ogmios transaction object.
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
import DanogoSwap from "danogo-clmm-sdk";
|
|
135
|
+
import { createInteractionContext, createChainSynchronizationClient } from "@cardano-ogmios/client";
|
|
136
|
+
|
|
137
|
+
const sdk = new DanogoSwap();
|
|
138
|
+
|
|
139
|
+
async function main() {
|
|
140
|
+
const context = await createInteractionContext(
|
|
141
|
+
console.error,
|
|
142
|
+
() => console.log("closed"),
|
|
143
|
+
{
|
|
144
|
+
connection: {
|
|
145
|
+
address: {
|
|
146
|
+
http: "YOUR_HTTP_ENDPOINT",
|
|
147
|
+
webSocket: "YOUR_WS_ENDPOINT",
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
}
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
const client = await createChainSynchronizationClient(context, {
|
|
154
|
+
rollForward: async ({ block }, requestNext) => {
|
|
155
|
+
if ("transactions" in block) {
|
|
156
|
+
for (const tx of block.transactions!) {
|
|
157
|
+
const pools = sdk.getPoolsFromOgmiosTx(tx);
|
|
158
|
+
// your logic here
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
requestNext();
|
|
163
|
+
},
|
|
164
|
+
|
|
165
|
+
rollBackward: async ({ point }, requestNext) => {
|
|
166
|
+
// ...
|
|
167
|
+
requestNext();
|
|
168
|
+
},
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
const checkpoint: Point = {
|
|
172
|
+
slot: 109847210, // Replace with your slot
|
|
173
|
+
id: "your_block_hash",
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
await client.resume([checkpoint]);
|
|
177
|
+
}
|
|
178
|
+
```
|
package/dist/sdk.d.mts
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { OutRef, LucidEvolution } from '@lucid-evolution/lucid';
|
|
2
|
+
import { Transaction } from '@cardano-ogmios/schema';
|
|
3
|
+
|
|
4
|
+
interface PoolDatum {
|
|
5
|
+
tokenX: string;
|
|
6
|
+
tokenY: string;
|
|
7
|
+
sqrtLowerPriceNum: bigint;
|
|
8
|
+
sqrtLowerPriceDen: bigint;
|
|
9
|
+
sqrtUpperPriceNum: bigint;
|
|
10
|
+
sqrtUpperPriceDen: bigint;
|
|
11
|
+
lpFeeRate: number;
|
|
12
|
+
platformFeeX: bigint;
|
|
13
|
+
platformFeeY: bigint;
|
|
14
|
+
minXChange: bigint;
|
|
15
|
+
minYChange: bigint;
|
|
16
|
+
circulatingLPToken: bigint;
|
|
17
|
+
lastWithdrawEpoch: number;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface MultiAsset {
|
|
21
|
+
policyId: string;
|
|
22
|
+
assets: Asset[];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
interface ConcentratedPool {
|
|
26
|
+
outRef: string;
|
|
27
|
+
address: string;
|
|
28
|
+
coin: bigint;
|
|
29
|
+
multiAssets: MultiAsset[];
|
|
30
|
+
validityNft: string;
|
|
31
|
+
tokenA: string;
|
|
32
|
+
tokenAReserve: bigint;
|
|
33
|
+
tokenB: string;
|
|
34
|
+
tokenBReserve: bigint;
|
|
35
|
+
lpFeeRate: number;
|
|
36
|
+
priceLowerNum: bigint;
|
|
37
|
+
priceLowerDen: bigint;
|
|
38
|
+
priceUpperNum: bigint;
|
|
39
|
+
priceUpperDen: bigint;
|
|
40
|
+
platformFeeA: bigint;
|
|
41
|
+
platformFeeB: bigint;
|
|
42
|
+
minAChange: bigint;
|
|
43
|
+
minBChange: bigint;
|
|
44
|
+
lpTokenTotalSupply: bigint;
|
|
45
|
+
lastWithdrawEpoch: number;
|
|
46
|
+
}
|
|
47
|
+
interface SwapRequest {
|
|
48
|
+
poolOutRef: OutRef;
|
|
49
|
+
poolScriptOutRef: OutRef;
|
|
50
|
+
deltaAmount: bigint;
|
|
51
|
+
minOutChangeAmount: bigint;
|
|
52
|
+
stakingOutRef?: OutRef;
|
|
53
|
+
}
|
|
54
|
+
interface QuoteSwapRequest {
|
|
55
|
+
poolOutRef: OutRef;
|
|
56
|
+
deltaAmount: bigint;
|
|
57
|
+
stakingOutRef?: OutRef;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
declare class DanogoSwap {
|
|
61
|
+
constructor();
|
|
62
|
+
/**
|
|
63
|
+
* Calculates the expected output amount for a swap in a specific liquidity pool.
|
|
64
|
+
*
|
|
65
|
+
* This function retrieves the latest pool state from the blockchain and performs a local calculation
|
|
66
|
+
* to estimate the swap outcome. It does not submit any transaction to the network.
|
|
67
|
+
*
|
|
68
|
+
* @param lucid An initialized Lucid instance used to query the blockchain.
|
|
69
|
+
* @param request The quote request object containing pool references and the swap amount.
|
|
70
|
+
* - `deltaAmount`: The amount of the input token to swap.
|
|
71
|
+
* - Positive (> 0): Swaps Token X for Token Y.
|
|
72
|
+
* - Negative (< 0): Swaps Token Y for Token X.
|
|
73
|
+
* @returns A promise that resolves to a `bigint` representing the estimated output token amount.
|
|
74
|
+
*/
|
|
75
|
+
calculateSwapOut(lucid: LucidEvolution, request: QuoteSwapRequest): Promise<bigint>;
|
|
76
|
+
/**
|
|
77
|
+
* Builds and submits a swap transaction to the network.
|
|
78
|
+
*
|
|
79
|
+
* @param lucid An initialized Lucid instance with a connected wallet.
|
|
80
|
+
* @param request The swap request object containing pool reference, swap amount, and minimum output.
|
|
81
|
+
* @returns A promise that resolves to the transaction hash.
|
|
82
|
+
*/
|
|
83
|
+
submitSwap(lucid: LucidEvolution, request: SwapRequest): Promise<string>;
|
|
84
|
+
/**
|
|
85
|
+
* Extracts concentrated liquidity pool data from a given Ogmios transaction.
|
|
86
|
+
*
|
|
87
|
+
* This method scans the transaction outputs for tokens associated with the configured
|
|
88
|
+
* pool script hash. When a pool NFT is detected, it decodes the inline datum and
|
|
89
|
+
* assets to return a structured `ConcentratedPool` object.
|
|
90
|
+
*
|
|
91
|
+
* @param tx The transaction object conforming to the Ogmios schema.
|
|
92
|
+
* @returns An array of `ConcentratedPool` objects found in the transaction outputs.
|
|
93
|
+
*/
|
|
94
|
+
getPoolsFromOgmiosTx(tx: Transaction, poolScriptHash: string): ConcentratedPool[];
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export { type ConcentratedPool, type PoolDatum, type SwapRequest, DanogoSwap as default };
|
package/dist/sdk.d.ts
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { OutRef, LucidEvolution } from '@lucid-evolution/lucid';
|
|
2
|
+
import { Transaction } from '@cardano-ogmios/schema';
|
|
3
|
+
|
|
4
|
+
interface PoolDatum {
|
|
5
|
+
tokenX: string;
|
|
6
|
+
tokenY: string;
|
|
7
|
+
sqrtLowerPriceNum: bigint;
|
|
8
|
+
sqrtLowerPriceDen: bigint;
|
|
9
|
+
sqrtUpperPriceNum: bigint;
|
|
10
|
+
sqrtUpperPriceDen: bigint;
|
|
11
|
+
lpFeeRate: number;
|
|
12
|
+
platformFeeX: bigint;
|
|
13
|
+
platformFeeY: bigint;
|
|
14
|
+
minXChange: bigint;
|
|
15
|
+
minYChange: bigint;
|
|
16
|
+
circulatingLPToken: bigint;
|
|
17
|
+
lastWithdrawEpoch: number;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface MultiAsset {
|
|
21
|
+
policyId: string;
|
|
22
|
+
assets: Asset[];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
interface ConcentratedPool {
|
|
26
|
+
outRef: string;
|
|
27
|
+
address: string;
|
|
28
|
+
coin: bigint;
|
|
29
|
+
multiAssets: MultiAsset[];
|
|
30
|
+
validityNft: string;
|
|
31
|
+
tokenA: string;
|
|
32
|
+
tokenAReserve: bigint;
|
|
33
|
+
tokenB: string;
|
|
34
|
+
tokenBReserve: bigint;
|
|
35
|
+
lpFeeRate: number;
|
|
36
|
+
priceLowerNum: bigint;
|
|
37
|
+
priceLowerDen: bigint;
|
|
38
|
+
priceUpperNum: bigint;
|
|
39
|
+
priceUpperDen: bigint;
|
|
40
|
+
platformFeeA: bigint;
|
|
41
|
+
platformFeeB: bigint;
|
|
42
|
+
minAChange: bigint;
|
|
43
|
+
minBChange: bigint;
|
|
44
|
+
lpTokenTotalSupply: bigint;
|
|
45
|
+
lastWithdrawEpoch: number;
|
|
46
|
+
}
|
|
47
|
+
interface SwapRequest {
|
|
48
|
+
poolOutRef: OutRef;
|
|
49
|
+
poolScriptOutRef: OutRef;
|
|
50
|
+
deltaAmount: bigint;
|
|
51
|
+
minOutChangeAmount: bigint;
|
|
52
|
+
stakingOutRef?: OutRef;
|
|
53
|
+
}
|
|
54
|
+
interface QuoteSwapRequest {
|
|
55
|
+
poolOutRef: OutRef;
|
|
56
|
+
deltaAmount: bigint;
|
|
57
|
+
stakingOutRef?: OutRef;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
declare class DanogoSwap {
|
|
61
|
+
constructor();
|
|
62
|
+
/**
|
|
63
|
+
* Calculates the expected output amount for a swap in a specific liquidity pool.
|
|
64
|
+
*
|
|
65
|
+
* This function retrieves the latest pool state from the blockchain and performs a local calculation
|
|
66
|
+
* to estimate the swap outcome. It does not submit any transaction to the network.
|
|
67
|
+
*
|
|
68
|
+
* @param lucid An initialized Lucid instance used to query the blockchain.
|
|
69
|
+
* @param request The quote request object containing pool references and the swap amount.
|
|
70
|
+
* - `deltaAmount`: The amount of the input token to swap.
|
|
71
|
+
* - Positive (> 0): Swaps Token X for Token Y.
|
|
72
|
+
* - Negative (< 0): Swaps Token Y for Token X.
|
|
73
|
+
* @returns A promise that resolves to a `bigint` representing the estimated output token amount.
|
|
74
|
+
*/
|
|
75
|
+
calculateSwapOut(lucid: LucidEvolution, request: QuoteSwapRequest): Promise<bigint>;
|
|
76
|
+
/**
|
|
77
|
+
* Builds and submits a swap transaction to the network.
|
|
78
|
+
*
|
|
79
|
+
* @param lucid An initialized Lucid instance with a connected wallet.
|
|
80
|
+
* @param request The swap request object containing pool reference, swap amount, and minimum output.
|
|
81
|
+
* @returns A promise that resolves to the transaction hash.
|
|
82
|
+
*/
|
|
83
|
+
submitSwap(lucid: LucidEvolution, request: SwapRequest): Promise<string>;
|
|
84
|
+
/**
|
|
85
|
+
* Extracts concentrated liquidity pool data from a given Ogmios transaction.
|
|
86
|
+
*
|
|
87
|
+
* This method scans the transaction outputs for tokens associated with the configured
|
|
88
|
+
* pool script hash. When a pool NFT is detected, it decodes the inline datum and
|
|
89
|
+
* assets to return a structured `ConcentratedPool` object.
|
|
90
|
+
*
|
|
91
|
+
* @param tx The transaction object conforming to the Ogmios schema.
|
|
92
|
+
* @returns An array of `ConcentratedPool` objects found in the transaction outputs.
|
|
93
|
+
*/
|
|
94
|
+
getPoolsFromOgmiosTx(tx: Transaction, poolScriptHash: string): ConcentratedPool[];
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export { type ConcentratedPool, type PoolDatum, type SwapRequest, DanogoSwap as default };
|
package/dist/sdk.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var _=Object.create;var T=Object.defineProperty;var G=Object.getOwnPropertyDescriptor;var Q=Object.getOwnPropertyNames;var V=Object.getPrototypeOf,z=Object.prototype.hasOwnProperty;var J=(n,e)=>{for(var t in e)T(n,t,{get:e[t],enumerable:!0})},q=(n,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of Q(e))!z.call(n,r)&&r!==t&&T(n,r,{get:()=>e[r],enumerable:!(o=G(e,r))||o.enumerable});return n};var K=(n,e,t)=>(t=n!=null?_(V(n)):{},q(e||!n||!n.__esModule?T(t,"default",{value:n,enumerable:!0}):t,n)),Z=n=>q(T({},"__esModule",{value:!0}),n);var ot={};J(ot,{default:()=>nt});module.exports=Z(ot);var S=require("@lucid-evolution/lucid");function D(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 l=0;l<r;l++)i[l+s]=parseInt(o.slice(l*2,l*2+2),16);return i}var v=(n,e)=>{try{return{kind:"selected",inputs:n,makeRedeemer:o=>{let r=3n,i=D(o[0],1),s=D(r,1),l=D(0n,1),g=D(e[0],32),p=i.length+s.length+i.length+l.length+g.length,u=new Uint8Array(p),a=0;return u.set(i,a),a+=i.length,u.set(s,a),a+=s.length,u.set(i,a),a+=i.length,u.set(l,a),a+=l.length,u.set(g,a),"5824"+Buffer.from(u).toString("hex")}}}catch(t){throw console.error("Error creating pool redeemer:",t),t}};var f=require("@lucid-evolution/lucid");var L=require("@lucid-evolution/lucid");function C(n,e,t){return L.Data.to(n,e,t)}var B=K(require("cbor")),Y=n=>{let e=f.Data.Tuple([f.Data.Bytes(),f.Data.Bytes()]),t=f.Data.Tuple([f.Data.Integer(),f.Data.Integer()],{hasConstr:!0}),o=f.Data.Tuple([e,e,f.Data.Integer(),f.Data.Integer(),f.Data.Integer(),t,t,f.Data.Integer(),f.Data.Integer(),f.Data.Integer(),f.Data.Integer()],{hasConstr:!0}),r=X(n.tokenX),i=X(n.tokenY),s=[r,i,BigInt(n.lpFeeRate),BigInt(n.platformFeeX),BigInt(n.platformFeeY),[BigInt(n.sqrtLowerPriceNum),BigInt(n.sqrtLowerPriceDen)],[BigInt(n.sqrtUpperPriceNum),BigInt(n.sqrtUpperPriceDen)],BigInt(n.minXChange),BigInt(n.minYChange),BigInt(n.circulatingLPToken),BigInt(n.lastWithdrawEpoch)];return C(s,o)},X=n=>{if(!n)return["",""];try{if(n.includes(".")){let o=n.split(".");return o.length===2?[o[0],o[1]]:[n,""]}let e=n.slice(0,56),t=n.slice(56);return[e,t]}catch(e){throw console.error(`Error parsing token ID "${n}":`,e),new Error(`Failed to parse token ID: ${n}`)}},F=n=>{let e=B.decodeFirstSync(Buffer.from(n,"hex")),t=e instanceof B.Tagged?e.value:e;if(!Array.isArray(t))throw new Error("Invalid datum structure: expected array of fields");let o=i=>{let s=i instanceof B.Tagged?i.value:i;if(Array.isArray(s)&&s.length===2){let l=s[0].toString("hex"),g=s[1].toString("hex");return l+g}throw new Error("Invalid AssetClass structure")},r=i=>{let s=i instanceof B.Tagged?i.value:i;if(Array.isArray(s)&&s.length===2)return{num:s[0],den:s[1]};throw new Error("Invalid Ratio structure")};return{tokenX:o(t[0]),tokenY:o(t[1]),lpFeeRate:Number(t[2]),platformFeeX:t[3].toString(),platformFeeY:t[4].toString(),sqrtLowerPriceNum:r(t[5]).num,sqrtLowerPriceDen:r(t[5]).den,sqrtUpperPriceNum:r(t[6]).num,sqrtUpperPriceDen:r(t[6]).den,minXChange:t[7].toString(),minYChange:t[8].toString(),circulatingLPToken:t[9].toString(),lastWithdrawEpoch:Number(t[10])}};var M=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 W=(n,e)=>{let t=432e6,o=1647899091e3,r=328;return e!=="Mainnet"&&(t=18e5),Math.floor((n-o)/t)+r};function N(n,e,t,o,r=0n){let i=o<0n?-o:o,s=t.tokenX===""?3000000n:0n,l=BigInt(n)-BigInt(t.platformFeeX)+r-s,g=BigInt(e)-BigInt(t.platformFeeY),p=tt(l,g,[BigInt(t.sqrtLowerPriceNum),BigInt(t.sqrtLowerPriceDen)],[BigInt(t.sqrtUpperPriceNum),BigInt(t.sqrtUpperPriceDen)]),u=H(p[0]*BigInt(t.sqrtUpperPriceDen),p[1]*BigInt(t.sqrtUpperPriceNum))+l,a=H(p[0]*BigInt(t.sqrtLowerPriceNum),p[1]*BigInt(t.sqrtLowerPriceDen))+g;return o>0n?$(i,u,a,g,BigInt(t.lpFeeRate)):$(i,a,u,l,BigInt(t.lpFeeRate))}var $=(n,e,t,o,r)=>{let i=10000n,l=n*r/i*5n/100n,g=i-r,p=e*i+n*g,u=e*t,m=(t*p-u*i)/p;if(m>o)throw new Error("pool out exceeded");return[m,l]},tt=(n,e,t,o)=>{let r=t[1]*o[1],i=t[0]*o[0],s=(e*r-n*i)*(e*r-n*i),l=4n*n*e*t[1]*t[1]*o[0]*o[0],g=et(s+l),p=e*r+n*i+g,u=2n*(o[0]*t[1]-o[1]*t[0]);return[p,u]};function et(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 H(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}var U=class{constructor(){}async calculateSwapOut(e,t){if(!e||!e.wallet())throw new Error("Please connect a wallet first.");let o=(await e.utxosByOutRef([{txHash:t.poolOutRef.txHash,outputIndex:t.poolOutRef.outputIndex}]))[0],r=null;if(t.stakingOutRef&&(r=(await e.utxosByOutRef([{txHash:t.stakingOutRef.txHash,outputIndex:t.stakingOutRef.outputIndex}]))[0]),!o.datum)throw new Error("Pool input UTxO does not contain a datum.");let i=F(o.datum),s=i.tokenX||"lovelace",l=i.tokenY,g=o.assets.lovelace,p=d=>{if(d==="lovelace")return g;for(let[b,x]of Object.entries(o.assets))if(b===d)return x;return 0n},u=e.newTx(),a=0n,m="";if(s=="lovelace"){m=(0,S.validatorToRewardAddress)(e.config().network,r.scriptRef);try{a=(await e.delegationAt(m)).rewards}catch{a=0n}}let[h,c]=N(p(s),p(l),i,t.deltaAmount,a);return h}async submitSwap(e,t){if(!e||!e.wallet())throw new Error("Please connect a wallet first.");let o=(await e.utxosByOutRef([{txHash:t.poolOutRef.txHash,outputIndex:t.poolOutRef.outputIndex}]))[0],r=(await e.utxosByOutRef([{txHash:t.poolScriptOutRef.txHash,outputIndex:t.poolScriptOutRef.outputIndex}]))[0],i=null;if(t.stakingOutRef&&(i=(await e.utxosByOutRef([{txHash:t.stakingOutRef.txHash,outputIndex:t.stakingOutRef.outputIndex}]))[0]),!o.datum)throw new Error("Pool input UTxO does not contain a datum.");let s=F(o.datum),l=s.tokenX||"lovelace",g=s.tokenY,p=o.assets.lovelace,u=R=>{if(R==="lovelace")return p;for(let[O,j]of Object.entries(o.assets))if(O===R)return j;return 0n},a=t.deltaAmount,m=a>0?l:g,h=a>0?g:l,c=e.newTx(),b=(await e.wallet().getUtxos()).reduce((R,O)=>R+(O.assets[m]||0n),0n),x=a<0n?-a:a;if(b<x)throw new Error(`Insufficient ${m} balance. Required: ${x}, Available: ${b}`);c=c.readFrom([r]),i&&(c=c.readFrom([i]));let w=0n,A="";if(l=="lovelace"){A=(0,S.validatorToRewardAddress)(e.config().network,i.scriptRef);try{w=(await e.delegationAt(A)).rewards}catch{w=0n}}let[y,E]=N(u(l),u(g),s,a,w);if(y<t.minOutChangeAmount)throw new Error(`Slippage too high. Expected at least ${t.minOutChangeAmount} but got ${y}`);let I=W(Date.now(),e.config().network),P=Y({...s,platformFeeX:BigInt(s.platformFeeX)+(m===s.tokenX?E:0n),platformFeeY:BigInt(s.platformFeeY)+(m===s.tokenY?E:0n),lastWithdrawEpoch:I}),k={...o.assets};return k[m]=k[m]+(a>0n?a:-a),k[h]=BigInt(k[h])-BigInt(y),c=c.pay.ToAddressWithData(o.address,{kind:"inline",value:P},k),c=c.attachMetadata(674,{msg:["Danogo Liquidity Pair: Swap"]}),c=c.collectFrom([o],v([o],[a])),c=c.withdraw((0,S.validatorToRewardAddress)(e.config().network,r.scriptRef),0n,v([o],[a])),l==="lovelace"&&I>s.lastWithdrawEpoch&&(c=c.withdraw(A,w,v([o],[a]))),c=c.validFrom(Date.now()-12e4).validTo(Date.now()+24e4).setMinFee(17000n).addSigner(await e.wallet().address()),await(await(await c.complete({localUPLCEval:!1})).sign.withWallet().complete()).submit()}getPoolsFromOgmiosTx(e,t){let o=[];return e.outputs.forEach((r,i)=>{let s=r.value,l=s[t];if(l&&r.datum){for(let[g,p]of Object.entries(l))if(p===1n){let u=t+g,a=`${e.id}#${i}`,m=s.ada.lovelace,h=M(s),c=F(r.datum),d=c.tokenX,b=c.tokenY,x=w=>{if(w==="lovelace"||w==="")return m;let A=w.slice(0,56),y=w.slice(56),I=h.find(P=>P.policyId===A)?.assets.find(P=>P.name===y);return I?I.value:0n};o.push({outRef:a,address:r.address,coin:m,multiAssets:h,validityNft:u,tokenA:d,tokenAReserve:x(d),tokenB:b,tokenBReserve:x(b),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})}}}),o}},nt=U;
|
package/dist/sdk.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{validatorToRewardAddress as O}from"@lucid-evolution/lucid";function T(n,e){let o=(n>=0n?n:n+(1n<<256n)).toString(16);o.length%2&&(o="0"+o);let s=o.length/2;if(s>e)throw new Error(`Number ${n} requires ${s} bytes, but target length is ${e}.`);let r=new Uint8Array(e),i=e-s;for(let l=0;l<s;l++)r[l+i]=parseInt(o.slice(l*2,l*2+2),16);return r}var D=(n,e)=>{try{return{kind:"selected",inputs:n,makeRedeemer:o=>{let s=3n,r=T(o[0],1),i=T(s,1),l=T(0n,1),g=T(e[0],32),p=r.length+i.length+r.length+l.length+g.length,u=new Uint8Array(p),a=0;return u.set(r,a),a+=r.length,u.set(i,a),a+=i.length,u.set(r,a),a+=r.length,u.set(l,a),a+=l.length,u.set(g,a),"5824"+Buffer.from(u).toString("hex")}}}catch(t){throw console.error("Error creating pool redeemer:",t),t}};import{Data as f}from"@lucid-evolution/lucid";import{Data as H}from"@lucid-evolution/lucid";function U(n,e,t){return H.to(n,e,t)}import*as B from"cbor";var L=n=>{let e=f.Tuple([f.Bytes(),f.Bytes()]),t=f.Tuple([f.Integer(),f.Integer()],{hasConstr:!0}),o=f.Tuple([e,e,f.Integer(),f.Integer(),f.Integer(),t,t,f.Integer(),f.Integer(),f.Integer(),f.Integer()],{hasConstr:!0}),s=q(n.tokenX),r=q(n.tokenY),i=[s,r,BigInt(n.lpFeeRate),BigInt(n.platformFeeX),BigInt(n.platformFeeY),[BigInt(n.sqrtLowerPriceNum),BigInt(n.sqrtLowerPriceDen)],[BigInt(n.sqrtUpperPriceNum),BigInt(n.sqrtUpperPriceDen)],BigInt(n.minXChange),BigInt(n.minYChange),BigInt(n.circulatingLPToken),BigInt(n.lastWithdrawEpoch)];return U(i,o)},q=n=>{if(!n)return["",""];try{if(n.includes(".")){let o=n.split(".");return o.length===2?[o[0],o[1]]:[n,""]}let e=n.slice(0,56),t=n.slice(56);return[e,t]}catch(e){throw console.error(`Error parsing token ID "${n}":`,e),new Error(`Failed to parse token ID: ${n}`)}},v=n=>{let e=B.decodeFirstSync(Buffer.from(n,"hex")),t=e instanceof B.Tagged?e.value:e;if(!Array.isArray(t))throw new Error("Invalid datum structure: expected array of fields");let o=r=>{let i=r instanceof B.Tagged?r.value:r;if(Array.isArray(i)&&i.length===2){let l=i[0].toString("hex"),g=i[1].toString("hex");return l+g}throw new Error("Invalid AssetClass structure")},s=r=>{let i=r instanceof B.Tagged?r.value:r;if(Array.isArray(i)&&i.length===2)return{num:i[0],den:i[1]};throw new Error("Invalid Ratio structure")};return{tokenX:o(t[0]),tokenY:o(t[1]),lpFeeRate:Number(t[2]),platformFeeX:t[3].toString(),platformFeeY:t[4].toString(),sqrtLowerPriceNum:s(t[5]).num,sqrtLowerPriceDen:s(t[5]).den,sqrtUpperPriceNum:s(t[6]).num,sqrtUpperPriceDen:s(t[6]).den,minXChange:t[7].toString(),minYChange:t[8].toString(),circulatingLPToken:t[9].toString(),lastWithdrawEpoch:Number(t[10])}};var C=n=>{if(!n||Object.keys(n).length===0)return[];let e=[];for(let[t,o]of Object.entries(n)){if(t==="ada")continue;let s=[];for(let[r,i]of Object.entries(o))s.push({name:r,value:i});e.push({policyId:t,assets:s})}return e};var M=(n,e)=>{let t=432e6,o=1647899091e3,s=328;return e!=="Mainnet"&&(t=18e5),Math.floor((n-o)/t)+s};function E(n,e,t,o,s=0n){let r=o<0n?-o:o,i=t.tokenX===""?3000000n:0n,l=BigInt(n)-BigInt(t.platformFeeX)+s-i,g=BigInt(e)-BigInt(t.platformFeeY),p=W(l,g,[BigInt(t.sqrtLowerPriceNum),BigInt(t.sqrtLowerPriceDen)],[BigInt(t.sqrtUpperPriceNum),BigInt(t.sqrtUpperPriceDen)]),u=Y(p[0]*BigInt(t.sqrtUpperPriceDen),p[1]*BigInt(t.sqrtUpperPriceNum))+l,a=Y(p[0]*BigInt(t.sqrtLowerPriceNum),p[1]*BigInt(t.sqrtLowerPriceDen))+g;return o>0n?X(r,u,a,g,BigInt(t.lpFeeRate)):X(r,a,u,l,BigInt(t.lpFeeRate))}var X=(n,e,t,o,s)=>{let r=10000n,l=n*s/r*5n/100n,g=r-s,p=e*r+n*g,u=e*t,m=(t*p-u*r)/p;if(m>o)throw new Error("pool out exceeded");return[m,l]},W=(n,e,t,o)=>{let s=t[1]*o[1],r=t[0]*o[0],i=(e*s-n*r)*(e*s-n*r),l=4n*n*e*t[1]*t[1]*o[0]*o[0],g=j(i+l),p=e*s+n*r+g,u=2n*(o[0]*t[1]-o[1]*t[0]);return[p,u]};function j(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 Y(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}var N=class{constructor(){}async calculateSwapOut(e,t){if(!e||!e.wallet())throw new Error("Please connect a wallet first.");let o=(await e.utxosByOutRef([{txHash:t.poolOutRef.txHash,outputIndex:t.poolOutRef.outputIndex}]))[0],s=null;if(t.stakingOutRef&&(s=(await e.utxosByOutRef([{txHash:t.stakingOutRef.txHash,outputIndex:t.stakingOutRef.outputIndex}]))[0]),!o.datum)throw new Error("Pool input UTxO does not contain a datum.");let r=v(o.datum),i=r.tokenX||"lovelace",l=r.tokenY,g=o.assets.lovelace,p=d=>{if(d==="lovelace")return g;for(let[b,x]of Object.entries(o.assets))if(b===d)return x;return 0n},u=e.newTx(),a=0n,m="";if(i=="lovelace"){m=O(e.config().network,s.scriptRef);try{a=(await e.delegationAt(m)).rewards}catch{a=0n}}let[h,c]=E(p(i),p(l),r,t.deltaAmount,a);return h}async submitSwap(e,t){if(!e||!e.wallet())throw new Error("Please connect a wallet first.");let o=(await e.utxosByOutRef([{txHash:t.poolOutRef.txHash,outputIndex:t.poolOutRef.outputIndex}]))[0],s=(await e.utxosByOutRef([{txHash:t.poolScriptOutRef.txHash,outputIndex:t.poolScriptOutRef.outputIndex}]))[0],r=null;if(t.stakingOutRef&&(r=(await e.utxosByOutRef([{txHash:t.stakingOutRef.txHash,outputIndex:t.stakingOutRef.outputIndex}]))[0]),!o.datum)throw new Error("Pool input UTxO does not contain a datum.");let i=v(o.datum),l=i.tokenX||"lovelace",g=i.tokenY,p=o.assets.lovelace,u=R=>{if(R==="lovelace")return p;for(let[S,$]of Object.entries(o.assets))if(S===R)return $;return 0n},a=t.deltaAmount,m=a>0?l:g,h=a>0?g:l,c=e.newTx(),b=(await e.wallet().getUtxos()).reduce((R,S)=>R+(S.assets[m]||0n),0n),x=a<0n?-a:a;if(b<x)throw new Error(`Insufficient ${m} balance. Required: ${x}, Available: ${b}`);c=c.readFrom([s]),r&&(c=c.readFrom([r]));let w=0n,A="";if(l=="lovelace"){A=O(e.config().network,r.scriptRef);try{w=(await e.delegationAt(A)).rewards}catch{w=0n}}let[y,F]=E(u(l),u(g),i,a,w);if(y<t.minOutChangeAmount)throw new Error(`Slippage too high. Expected at least ${t.minOutChangeAmount} but got ${y}`);let I=M(Date.now(),e.config().network),P=L({...i,platformFeeX:BigInt(i.platformFeeX)+(m===i.tokenX?F:0n),platformFeeY:BigInt(i.platformFeeY)+(m===i.tokenY?F:0n),lastWithdrawEpoch:I}),k={...o.assets};return k[m]=k[m]+(a>0n?a:-a),k[h]=BigInt(k[h])-BigInt(y),c=c.pay.ToAddressWithData(o.address,{kind:"inline",value:P},k),c=c.attachMetadata(674,{msg:["Danogo Liquidity Pair: Swap"]}),c=c.collectFrom([o],D([o],[a])),c=c.withdraw(O(e.config().network,s.scriptRef),0n,D([o],[a])),l==="lovelace"&&I>i.lastWithdrawEpoch&&(c=c.withdraw(A,w,D([o],[a]))),c=c.validFrom(Date.now()-12e4).validTo(Date.now()+24e4).setMinFee(17000n).addSigner(await e.wallet().address()),await(await(await c.complete({localUPLCEval:!1})).sign.withWallet().complete()).submit()}getPoolsFromOgmiosTx(e,t){let o=[];return e.outputs.forEach((s,r)=>{let i=s.value,l=i[t];if(l&&s.datum){for(let[g,p]of Object.entries(l))if(p===1n){let u=t+g,a=`${e.id}#${r}`,m=i.ada.lovelace,h=C(i),c=v(s.datum),d=c.tokenX,b=c.tokenY,x=w=>{if(w==="lovelace"||w==="")return m;let A=w.slice(0,56),y=w.slice(56),I=h.find(P=>P.policyId===A)?.assets.find(P=>P.name===y);return I?I.value:0n};o.push({outRef:a,address:s.address,coin:m,multiAssets:h,validityNft:u,tokenA:d,tokenAReserve:x(d),tokenB:b,tokenBReserve:x(b),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})}}}),o}},ut=N;export{ut as default};
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "danogo-clmm",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "An SDK to calculate and execute swaps on the Danogo liquidity platform with Lucid Evolution.",
|
|
5
|
+
"main": "./dist/sdk.js",
|
|
6
|
+
"module": "./dist/sdk.mjs",
|
|
7
|
+
"types": "./dist/sdk.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsup src/sdk.ts --format cjs,esm --dts --minify --clean --no-splitting",
|
|
13
|
+
"prepublishOnly": "npm run build"
|
|
14
|
+
},
|
|
15
|
+
"publishConfig": {
|
|
16
|
+
"access": "public"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@lucid-evolution/lucid": "0.4.29",
|
|
20
|
+
"cbor": "^10.0.11"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"ts-node": "^10.9.2",
|
|
24
|
+
"tsup": "^8.0.0",
|
|
25
|
+
"typescript": "^5.9.2"
|
|
26
|
+
},
|
|
27
|
+
"peerDependencies": {
|
|
28
|
+
"@lucid-evolution/lucid": "0.4.29"
|
|
29
|
+
}
|
|
30
|
+
}
|