@andrewkimjoseph/celina-sdk 0.6.0 → 0.7.1

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.
Files changed (33) hide show
  1. package/README.md +22 -9
  2. package/build/abis/gooddollar-broker.d.ts +77 -0
  3. package/build/abis/gooddollar-broker.js +44 -0
  4. package/build/abis/gooddollar-broker.js.map +1 -0
  5. package/build/analytics/mcp-tool-events.js +3 -0
  6. package/build/analytics/mcp-tool-events.js.map +1 -1
  7. package/build/config/gooddollar.d.ts +12 -0
  8. package/build/config/gooddollar.js +19 -0
  9. package/build/config/gooddollar.js.map +1 -1
  10. package/build/index.d.ts +3 -2
  11. package/build/index.js +1 -1
  12. package/build/index.js.map +1 -1
  13. package/build/services/ens.service.d.ts +1 -1
  14. package/build/services/ens.service.js +1 -1
  15. package/build/services/gooddollar.service.d.ts +57 -1
  16. package/build/services/gooddollar.service.js +256 -4
  17. package/build/services/gooddollar.service.js.map +1 -1
  18. package/build/services/transaction.service.d.ts +1 -1
  19. package/build/services/transaction.service.js +1 -1
  20. package/build/tools/domains/browser.js +3 -3
  21. package/build/tools/domains/browser.js.map +1 -1
  22. package/build/tools/domains/gooddollar.js +82 -1
  23. package/build/tools/domains/gooddollar.js.map +1 -1
  24. package/build/tools/schemas/common.d.ts +39 -0
  25. package/build/tools/schemas/common.js +11 -1
  26. package/build/tools/schemas/common.js.map +1 -1
  27. package/build/tools/swap-routing.d.ts +2 -2
  28. package/build/tools/swap-routing.js +68 -7
  29. package/build/tools/swap-routing.js.map +1 -1
  30. package/build/tools/types.d.ts +8 -0
  31. package/build/types/prepared.d.ts +1 -1
  32. package/package.json +1 -1
  33. package/tests/catalog/domains/defi.ts +179 -0
@@ -1,3 +1,4 @@
1
+ import { isGoodDollarUsdReservePair } from "../config/gooddollar.js";
1
2
  function parseExpectedOut(value) {
2
3
  const n = Number(value.replace(/,/g, ""));
3
4
  return Number.isFinite(n) ? n : 0;
@@ -8,12 +9,31 @@ function isMentoRouteError(message) {
8
9
  function isUniswapRouteError(message) {
9
10
  return /no uniswap v4 route|insufficient liquidity in uniswap v4/i.test(message);
10
11
  }
12
+ function isGoodDollarReserveRouteError(message) {
13
+ return /no gooddollar reserve route/i.test(message);
14
+ }
11
15
  function isInsufficientBalanceError(message) {
12
16
  return /insufficient .+ balance/i.test(message);
13
17
  }
14
18
  function rejectionMessage(reason) {
15
19
  return reason instanceof Error ? reason.message : String(reason);
16
20
  }
21
+ function filterAlternatives(best, others) {
22
+ if (best.protocol !== "gooddollar_reserve") {
23
+ return others;
24
+ }
25
+ const bestOut = parseExpectedOut(best.expectedOut);
26
+ if (bestOut <= 0) {
27
+ return others;
28
+ }
29
+ return others.filter((alt) => {
30
+ if (alt.protocol !== "uniswap_v4" || alt.error) {
31
+ return true;
32
+ }
33
+ const altOut = parseExpectedOut(alt.expectedOut);
34
+ return altOut >= bestOut * 0.95;
35
+ });
36
+ }
17
37
  async function tryMentoQuote(celina, tokenIn, tokenOut, amount, from) {
18
38
  const quote = await celina.mentoFx.getFxQuote(tokenIn, tokenOut, amount, from);
19
39
  return {
@@ -38,12 +58,32 @@ async function tryUniswapQuote(celina, tokenIn, tokenOut, amount, from) {
38
58
  network: quote.network,
39
59
  };
40
60
  }
41
- /** Quote a swap across Mento FX and Uniswap v4; returns the best available route. */
61
+ async function tryGoodDollarReserveQuote(celina, tokenIn, tokenOut, amount, from) {
62
+ const quote = await celina.gooddollar.getReserveQuote(tokenIn, tokenOut, amount, from);
63
+ return {
64
+ protocol: "gooddollar_reserve",
65
+ tokenIn: quote.tokenIn,
66
+ tokenOut: quote.tokenOut,
67
+ amountIn: quote.amountIn,
68
+ expectedOut: quote.expectedOut,
69
+ routeHops: quote.routeHops,
70
+ network: quote.network,
71
+ };
72
+ }
73
+ /** Quote a swap across Mento FX, GoodDollar reserve, and Uniswap v4; returns the best route. */
42
74
  export async function getSwapQuoteWithFallback(celina, tokenIn, tokenOut, amount, from) {
43
- const [mentoResult, uniswapResult] = await Promise.allSettled([
75
+ const reserveEligible = isGoodDollarUsdReservePair(tokenIn, tokenOut);
76
+ const quoteTasks = [
44
77
  tryMentoQuote(celina, tokenIn, tokenOut, amount, from),
45
78
  tryUniswapQuote(celina, tokenIn, tokenOut, amount, from),
46
- ]);
79
+ ];
80
+ if (reserveEligible) {
81
+ quoteTasks.push(tryGoodDollarReserveQuote(celina, tokenIn, tokenOut, amount, from));
82
+ }
83
+ const results = await Promise.allSettled(quoteTasks);
84
+ const mentoResult = results[0];
85
+ const uniswapResult = results[1];
86
+ const reserveResult = reserveEligible ? results[2] : undefined;
47
87
  const successes = [];
48
88
  const alternatives = [];
49
89
  if (mentoResult.status === "fulfilled") {
@@ -64,22 +104,37 @@ export async function getSwapQuoteWithFallback(celina, tokenIn, tokenOut, amount
64
104
  alternatives.push({ protocol: "uniswap_v4", expectedOut: "0", error: message });
65
105
  }
66
106
  }
107
+ if (reserveResult) {
108
+ if (reserveResult.status === "fulfilled") {
109
+ successes.push(reserveResult.value);
110
+ }
111
+ else {
112
+ const message = rejectionMessage(reserveResult.reason);
113
+ if (!isGoodDollarReserveRouteError(message)) {
114
+ alternatives.push({
115
+ protocol: "gooddollar_reserve",
116
+ expectedOut: "0",
117
+ error: message,
118
+ });
119
+ }
120
+ }
121
+ }
67
122
  if (successes.length === 0) {
68
- const failures = [mentoResult, uniswapResult]
123
+ const failures = results
69
124
  .filter((result) => result.status === "rejected")
70
125
  .map((result) => rejectionMessage(result.reason));
71
126
  const balanceError = failures.find(isInsufficientBalanceError);
72
127
  if (balanceError) {
73
128
  throw new Error(balanceError);
74
129
  }
75
- throw new Error(`No swap route for ${tokenIn} → ${tokenOut} via Mento FX or Uniswap v4.`);
130
+ throw new Error(`No swap route for ${tokenIn} → ${tokenOut} via Mento FX, GoodDollar reserve, or Uniswap v4.`);
76
131
  }
77
132
  successes.sort((a, b) => parseExpectedOut(b.expectedOut) - parseExpectedOut(a.expectedOut));
78
133
  const best = successes[0];
79
- const otherProtocols = successes.slice(1).map((q) => ({
134
+ const otherProtocols = filterAlternatives(best, successes.slice(1).map((q) => ({
80
135
  protocol: q.protocol,
81
136
  expectedOut: q.expectedOut,
82
- }));
137
+ })));
83
138
  return {
84
139
  ...best,
85
140
  alternatives: otherProtocols.length > 0 ? otherProtocols : alternatives,
@@ -96,6 +151,12 @@ export async function prepareSwapWithFallback(celina, from, tokenIn, tokenOut, a
96
151
  deadlineMinutes: params?.deadlineMinutes,
97
152
  });
98
153
  }
154
+ if (chosen === "gooddollar_reserve") {
155
+ return celina.gooddollar.prepareReserveSwap(from, tokenIn, tokenOut, amount, {
156
+ recipient: params?.recipient,
157
+ slippageTolerance: params?.slippageTolerance,
158
+ });
159
+ }
99
160
  return celina.uniswap.prepareSwap(from, tokenIn, tokenOut, amount, {
100
161
  recipient: params?.recipient,
101
162
  slippageTolerance: params?.slippageTolerance,
@@ -1 +1 @@
1
- {"version":3,"file":"swap-routing.js","sourceRoot":"","sources":["../../src/tools/swap-routing.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"swap-routing.js","sourceRoot":"","sources":["../../src/tools/swap-routing.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AAyBrE,SAAS,gBAAgB,CAAC,KAAa;IACrC,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;IAC1C,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACpC,CAAC;AAED,SAAS,iBAAiB,CAAC,OAAe;IACxC,OAAO,wDAAwD,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAChF,CAAC;AAED,SAAS,mBAAmB,CAAC,OAAe;IAC1C,OAAO,2DAA2D,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACnF,CAAC;AAED,SAAS,6BAA6B,CAAC,OAAe;IACpD,OAAO,8BAA8B,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACtD,CAAC;AAED,SAAS,0BAA0B,CAAC,OAAe;IACjD,OAAO,0BAA0B,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,gBAAgB,CAAC,MAAe;IACvC,OAAO,MAAM,YAAY,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AACnE,CAAC;AAED,SAAS,kBAAkB,CACzB,IAAqB,EACrB,MAAoD;IAEpD,IAAI,IAAI,CAAC,QAAQ,KAAK,oBAAoB,EAAE,CAAC;QAC3C,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,OAAO,GAAG,gBAAgB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACnD,IAAI,OAAO,IAAI,CAAC,EAAE,CAAC;QACjB,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE;QAC3B,IAAI,GAAG,CAAC,QAAQ,KAAK,YAAY,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;YAC/C,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,MAAM,GAAG,gBAAgB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACjD,OAAO,MAAM,IAAI,OAAO,GAAG,IAAI,CAAC;IAClC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,aAAa,CAC1B,MAAoB,EACpB,OAAe,EACf,QAAgB,EAChB,MAAc,EACd,IAAoB;IAEpB,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;IAC/E,OAAO;QACL,QAAQ,EAAE,UAAmB;QAC7B,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,OAAO,EAAE,KAAK,CAAC,OAAO;KACvB,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,eAAe,CAC5B,MAAoB,EACpB,OAAe,EACf,QAAgB,EAChB,MAAc,EACd,IAAoB;IAEpB,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;IACjF,OAAO;QACL,QAAQ,EAAE,YAAqB;QAC/B,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,OAAO,EAAE,KAAK,CAAC,OAAO;KACvB,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,yBAAyB,CACtC,MAAoB,EACpB,OAAe,EACf,QAAgB,EAChB,MAAc,EACd,IAAoB;IAEpB,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,eAAe,CACnD,OAAO,EACP,QAAQ,EACR,MAAM,EACN,IAAI,CACL,CAAC;IACF,OAAO;QACL,QAAQ,EAAE,oBAA6B;QACvC,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,OAAO,EAAE,KAAK,CAAC,OAAO;KACvB,CAAC;AACJ,CAAC;AAED,gGAAgG;AAChG,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,MAAoB,EACpB,OAAe,EACf,QAAgB,EAChB,MAAc,EACd,IAAoB;IAEpB,MAAM,eAAe,GAAG,0BAA0B,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAEtE,MAAM,UAAU,GAA+B;QAC7C,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC;QACtD,eAAe,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC;KACzD,CAAC;IAEF,IAAI,eAAe,EAAE,CAAC;QACpB,UAAU,CAAC,IAAI,CACb,yBAAyB,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,CACnE,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;IAErD,MAAM,WAAW,GAAG,OAAO,CAAC,CAAC,CAAE,CAAC;IAChC,MAAM,aAAa,GAAG,OAAO,CAAC,CAAC,CAAE,CAAC;IAClC,MAAM,aAAa,GAAG,eAAe,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAE/D,MAAM,SAAS,GAAsB,EAAE,CAAC;IACxC,MAAM,YAAY,GAAoC,EAAE,CAAC;IAEzD,IAAI,WAAW,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;QACvC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC;SAAM,CAAC;QACN,MAAM,OAAO,GAAG,gBAAgB,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QACrD,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,EAAE,CAAC;YAChC,YAAY,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;QAChF,CAAC;IACH,CAAC;IAED,IAAI,aAAa,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;QACzC,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IACtC,CAAC;SAAM,CAAC;QACN,MAAM,OAAO,GAAG,gBAAgB,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QACvD,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,EAAE,CAAC;YAClC,YAAY,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;QAClF,CAAC;IACH,CAAC;IAED,IAAI,aAAa,EAAE,CAAC;QAClB,IAAI,aAAa,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YACzC,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACtC,CAAC;aAAM,CAAC;YACN,MAAM,OAAO,GAAG,gBAAgB,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;YACvD,IAAI,CAAC,6BAA6B,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC5C,YAAY,CAAC,IAAI,CAAC;oBAChB,QAAQ,EAAE,oBAAoB;oBAC9B,WAAW,EAAE,GAAG;oBAChB,KAAK,EAAE,OAAO;iBACf,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,OAAO;aACrB,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,KAAK,UAAU,CAAC;aAChD,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QAEpD,MAAM,YAAY,GAAG,QAAQ,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QAC/D,IAAI,YAAY,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC;QAChC,CAAC;QAED,MAAM,IAAI,KAAK,CACb,qBAAqB,OAAO,MAAM,QAAQ,mDAAmD,CAC9F,CAAC;IACJ,CAAC;IAED,SAAS,CAAC,IAAI,CACZ,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,WAAW,CAAC,CAC5E,CAAC;IAEF,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAE,CAAC;IAC3B,MAAM,cAAc,GAAG,kBAAkB,CACvC,IAAI,EACJ,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC7B,QAAQ,EAAE,CAAC,CAAC,QAAQ;QACpB,WAAW,EAAE,CAAC,CAAC,WAAW;KAC3B,CAAC,CAAC,CACJ,CAAC;IAEF,OAAO;QACL,GAAG,IAAI;QACP,YAAY,EAAE,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,YAAY;KACxE,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,MAAoB,EACpB,IAAmB,EACnB,OAAe,EACf,QAAgB,EAChB,MAAc,EACd,MAA0B,EAC1B,QAAuB;IAEvB,MAAM,MAAM,GACV,QAAQ;QACR,CAAC,MAAM,wBAAwB,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;aACtE,QAAQ,CAAC;IAEd,IAAI,MAAM,KAAK,UAAU,EAAE,CAAC;QAC1B,OAAO,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE;YAC/D,SAAS,EAAE,MAAM,EAAE,SAAS;YAC5B,iBAAiB,EAAE,MAAM,EAAE,iBAAiB;YAC5C,eAAe,EAAE,MAAM,EAAE,eAAe;SACzC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,MAAM,KAAK,oBAAoB,EAAE,CAAC;QACpC,OAAO,MAAM,CAAC,UAAU,CAAC,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE;YAC3E,SAAS,EAAE,MAAM,EAAE,SAAS;YAC5B,iBAAiB,EAAE,MAAM,EAAE,iBAAiB;SAC7C,CAAC,CAAC;IACL,CAAC;IAED,OAAO,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE;QACjE,SAAS,EAAE,MAAM,EAAE,SAAS;QAC5B,iBAAiB,EAAE,MAAM,EAAE,iBAAiB;QAC5C,eAAe,EAAE,MAAM,EAAE,eAAe;KACzC,CAAC,CAAC;AACL,CAAC"}
@@ -83,6 +83,14 @@ export type CarbonWriteExecutors = {
83
83
  };
84
84
  export type GoodDollarWriteExecutors = {
85
85
  claimDailyUbi: () => Promise<unknown>;
86
+ estimateReserveSwap: (tokenIn: string, tokenOut: string, amount: string, options?: {
87
+ recipient?: `0x${string}`;
88
+ slippageTolerance?: number;
89
+ }) => Promise<unknown>;
90
+ executeReserveSwap: (tokenIn: string, tokenOut: string, amount: string, options?: {
91
+ recipient?: `0x${string}`;
92
+ slippageTolerance?: number;
93
+ }) => Promise<unknown>;
86
94
  };
87
95
  export type SelfExecutors = {
88
96
  verifyAgent: (args: Record<string, unknown>) => Promise<unknown>;
@@ -18,7 +18,7 @@ export interface PreparedFlow {
18
18
  }
19
19
  /**
20
20
  * JSON-safe prepared flow returned by prepare* tools and chat APIs.
21
- * Consumers (celina-agent TxConfirmCard, wagmi) iterate steps and call sendTransaction.
21
+ * Consumers (celina-agent TxConfirmCard, wagmi) iterate steps and call sendTransactionAsync (wagmi) or walletClient.sendTransaction (viem).
22
22
  */
23
23
  export interface SerializedPreparedFlow extends Omit<PreparedFlow, "steps"> {
24
24
  steps: PreparedTx[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@andrewkimjoseph/celina-sdk",
3
- "version": "0.6.0",
3
+ "version": "0.7.1",
4
4
  "description": "Celina SDK — Celo mainnet reads and unsigned transaction preparation for frontend apps.",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -1,5 +1,7 @@
1
1
  import type { OperationSpec } from "../types.js";
2
2
  import { assertHasKeys } from "../../helpers/assert.js";
3
+ import { getSwapQuoteWithFallback } from "../../../src/tools/swap-routing.js";
4
+ import { GOODDOLLAR_MENTO_BROKER } from "../../../src/config/gooddollar.js";
3
5
 
4
6
  function fromAddress(fx: Parameters<OperationSpec["assert"]>[1]): `0x${string}` {
5
7
  return fx.signerAddress ?? fx.wallet;
@@ -310,4 +312,181 @@ export const gooddollarOperations: OperationSpec[] = [
310
312
  assertHasKeys(result, ["hash"]);
311
313
  },
312
314
  },
315
+ {
316
+ id: "gooddollar.getReserveQuote.sell",
317
+ domain: "gooddollar",
318
+ layer: "read",
319
+ sdk: {
320
+ invoke: (client) =>
321
+ client.gooddollar.getReserveQuote("GoodDollar", "USDm", "1000"),
322
+ },
323
+ mcp: {
324
+ tool: "get_gooddollar_reserve_quote",
325
+ arguments: () => ({
326
+ token_in: "GoodDollar",
327
+ token_out: "USDm",
328
+ amount: "1000",
329
+ }),
330
+ },
331
+ assert: (result) => {
332
+ const quote = result as { protocol?: string; expectedOut?: string };
333
+ if (quote.protocol !== "gooddollar_reserve") {
334
+ throw new Error(`Expected gooddollar_reserve, got ${quote.protocol}`);
335
+ }
336
+ if (parseExpectedOut(quote.expectedOut) <= 0) {
337
+ throw new Error("Expected positive reserve output for G$ → USDm");
338
+ }
339
+ },
340
+ },
341
+ {
342
+ id: "gooddollar.getReserveQuote.buy",
343
+ domain: "gooddollar",
344
+ layer: "read",
345
+ sdk: {
346
+ invoke: (client) =>
347
+ client.gooddollar.getReserveQuote("USDm", "GoodDollar", "100"),
348
+ },
349
+ mcp: {
350
+ tool: "get_gooddollar_reserve_quote",
351
+ arguments: () => ({
352
+ token_in: "USDm",
353
+ token_out: "GoodDollar",
354
+ amount: "100",
355
+ }),
356
+ },
357
+ assert: (result) => {
358
+ const quote = result as { protocol?: string; expectedOut?: string };
359
+ if (quote.protocol !== "gooddollar_reserve") {
360
+ throw new Error(`Expected gooddollar_reserve, got ${quote.protocol}`);
361
+ }
362
+ if (parseExpectedOut(quote.expectedOut) <= 1000) {
363
+ throw new Error("Expected reserve to return substantially more G$ than Uniswap");
364
+ }
365
+ },
366
+ },
367
+ {
368
+ id: "swap.getSwapQuoteWithFallback.gdUsd",
369
+ domain: "swap",
370
+ layer: "read",
371
+ sdk: {
372
+ invoke: (client) =>
373
+ getSwapQuoteWithFallback(client, "GoodDollar", "USDm", "1000"),
374
+ },
375
+ assert: (result) => {
376
+ const quote = result as { protocol?: string };
377
+ if (quote.protocol !== "gooddollar_reserve") {
378
+ throw new Error(`Expected gooddollar_reserve, got ${quote.protocol}`);
379
+ }
380
+ },
381
+ },
382
+ {
383
+ id: "swap.getSwapQuoteWithFallback.usdGd",
384
+ domain: "swap",
385
+ layer: "read",
386
+ sdk: {
387
+ invoke: (client) =>
388
+ getSwapQuoteWithFallback(client, "USDm", "GoodDollar", "100"),
389
+ },
390
+ assert: (result) => {
391
+ const quote = result as { protocol?: string };
392
+ if (quote.protocol !== "gooddollar_reserve") {
393
+ throw new Error(`Expected gooddollar_reserve, got ${quote.protocol}`);
394
+ }
395
+ },
396
+ },
397
+ {
398
+ id: "gooddollar.prepareReserveSwap.sell",
399
+ domain: "gooddollar",
400
+ layer: "prepare",
401
+ requiresEnv: ["CELO_PRIVATE_KEY"],
402
+ sdk: {
403
+ invoke: (client, fx) =>
404
+ client.gooddollar.prepareReserveSwap(
405
+ fromAddress(fx),
406
+ "GoodDollar",
407
+ "USDm",
408
+ "1000",
409
+ ),
410
+ },
411
+ assert: (result) => {
412
+ const flow = result as { steps?: Array<{ to?: string }> };
413
+ assertHasKeys(result, ["from", "steps"]);
414
+ const last = flow.steps?.at(-1);
415
+ if (last?.to?.toLowerCase() !== GOODDOLLAR_MENTO_BROKER.toLowerCase()) {
416
+ throw new Error("Expected final reserve swap step to target MentoBroker");
417
+ }
418
+ },
419
+ },
420
+ {
421
+ id: "gooddollar.prepareReserveSwap.buy",
422
+ domain: "gooddollar",
423
+ layer: "prepare",
424
+ requiresEnv: ["CELO_PRIVATE_KEY"],
425
+ sdk: {
426
+ invoke: (client, fx) =>
427
+ client.gooddollar.prepareReserveSwap(
428
+ fromAddress(fx),
429
+ "USDm",
430
+ "GoodDollar",
431
+ "10",
432
+ ),
433
+ },
434
+ assert: (result) => {
435
+ const flow = result as { steps?: Array<{ to?: string }> };
436
+ assertHasKeys(result, ["from", "steps"]);
437
+ const last = flow.steps?.at(-1);
438
+ if (last?.to?.toLowerCase() !== GOODDOLLAR_MENTO_BROKER.toLowerCase()) {
439
+ throw new Error("Expected final reserve swap step to target MentoBroker");
440
+ }
441
+ },
442
+ },
443
+ {
444
+ id: "gooddollar.estimateReserveSwap.sell",
445
+ domain: "gooddollar",
446
+ layer: "read",
447
+ requiresEnv: ["CELO_PRIVATE_KEY"],
448
+ sdk: {
449
+ invoke: (client, fx) =>
450
+ client.gooddollar.estimateReserveSwap(
451
+ fromAddress(fx),
452
+ "GoodDollar",
453
+ "USDm",
454
+ "1000",
455
+ ),
456
+ },
457
+ mcp: {
458
+ tool: "estimate_gooddollar_reserve_swap",
459
+ arguments: () => ({
460
+ token_in: "GoodDollar",
461
+ token_out: "USDm",
462
+ amount: "1000",
463
+ }),
464
+ },
465
+ assert: (result) => {
466
+ assertHasKeys(result, ["expectedOut", "approvalNeeded", "swapGas"]);
467
+ },
468
+ },
469
+ {
470
+ id: "gooddollar.executeReserveSwap.sell",
471
+ domain: "gooddollar",
472
+ layer: "write",
473
+ requiresEnv: ["CELO_PRIVATE_KEY"],
474
+ requiresWrites: true,
475
+ mcp: {
476
+ tool: "execute_gooddollar_reserve_swap",
477
+ arguments: () => ({
478
+ token_in: "GoodDollar",
479
+ token_out: "USDm",
480
+ amount: "1",
481
+ }),
482
+ },
483
+ assert: (result) => {
484
+ assertHasKeys(result, ["hash"]);
485
+ },
486
+ },
313
487
  ];
488
+
489
+ function parseExpectedOut(value: string | undefined): number {
490
+ const n = Number(String(value ?? "").replace(/,/g, ""));
491
+ return Number.isFinite(n) ? n : 0;
492
+ }