Skip to content

Commit

Permalink
feat: add sponsored tx broadcast
Browse files Browse the repository at this point in the history
  • Loading branch information
zhigang1992 committed Dec 11, 2024
1 parent 5d3dea0 commit 921ab32
Show file tree
Hide file tree
Showing 10 changed files with 526 additions and 20 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"packageManager": "pnpm@9.4.0",
"version": "3.0.0-beta.1",
"version": "3.0.0-beta.3",
"license": "MIT",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
Expand Down
12 changes: 7 additions & 5 deletions scripts/gen-contract.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { generateContracts } from 'clarity-codegen/lib/generate';
import * as path from 'path';
import * as path from 'node:path';
import { configs } from '../src/config';

const API_HOST = 'https://stacks-node-api.alexlab.co';
const CONTRACT_DEPLOYER = 'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM';
const API_HOST = configs.READONLY_CALL_API_HOST;
const ALEX_CONTRACT_DEPLOYER = configs.CONTRACT_DEPLOYER;
const SPONSOR_CONTRACT_DEPLOYER = configs.SPONSOR_TX_DEPLOYER;

const contracts = ['amm-pool-v2-01'];
const contracts = ['amm-pool-v2-01', 'sponsor-dex-v01'];

(async function main() {
await generateContracts(
API_HOST,
CONTRACT_DEPLOYER,
(contract) => contract === 'sponsor-dex-v01' ? SPONSOR_CONTRACT_DEPLOYER : ALEX_CONTRACT_DEPLOYER,
contracts,
path.resolve(__dirname, '../src/generated/smartContract/'),
'Alex',
Expand Down
98 changes: 95 additions & 3 deletions src/alexSDK.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Currency } from './currency';
import { runSpot, TxToBroadCast } from './helpers/SwapHelper';
import { runSpot, type TxToBroadCast } from './helpers/SwapHelper';
import { getLiquidityProviderFee } from './helpers/FeeHelper';
import { AlexSDKResponse, PoolData, PriceData, TokenInfo } from './types';
import type { AlexSDKResponse, PoolData, PriceData, TokenInfo } from './types';
import {
fetchBalanceForAccount,
getAlexSDKData,
Expand All @@ -10,7 +10,8 @@ import {
import { getAllPossibleRoute } from './helpers/RouteHelper';
import { getYAmountFromXAmount } from './helpers/RateHelper';
import { fromEntries } from './utils/utils';
import { AMMRoute } from './utils/ammRouteResolver';
import type { AMMRoute } from './utils/ammRouteResolver';
import { broadcastSponsoredTx, requiredStxAmountForSponsorTx, runSponsoredSpotTx } from './helpers/SponsorTxHelper';

Check failure on line 14 in src/alexSDK.ts

View workflow job for this annotation

GitHub Actions / build

Replace `·broadcastSponsoredTx,·requiredStxAmountForSponsorTx,·runSponsoredSpotTx·` with `⏎··broadcastSponsoredTx,⏎··requiredStxAmountForSponsorTx,⏎··runSponsoredSpotTx,⏎`

/**
* The AlexSDK class provides methods for interacting with a decentralized exchange (DEX) system,
Expand Down Expand Up @@ -163,6 +164,43 @@ export class AlexSDK {
);
}

/**
* Get the amount of destination currency that will be received when swapping from one currency to another

Check failure on line 168 in src/alexSDK.ts

View workflow job for this annotation

GitHub Actions / build

Delete `·`
* in the context of sponsor tx.
*
* @param {Currency} from - The currency to swap from.
* @param {bigint} fromAmount - The amount of the source currency to swap.
* @param {Currency} to - The currency to swap to.
* @param {AMMRoute} [customRoute] - An optional custom route for the swap.
* @returns {Promise<bigint>} - A promise that resolves to a bigint representing the amount of the destination currency that will be received.
*/
async getAmountToForSponsorTx(
from: Currency,
fromAmount: bigint,
to: Currency,
customRoute?: AMMRoute
): Promise<bigint> {
const route = customRoute ?? await this.getRoute(from, to)

Check failure on line 183 in src/alexSDK.ts

View workflow job for this annotation

GitHub Actions / build

Replace `await·this.getRoute(from,·to)` with `(await·this.getRoute(from,·to));`
const stxAmount = await requiredStxAmountForSponsorTx(

Check failure on line 184 in src/alexSDK.ts

View workflow job for this annotation

GitHub Actions / build

Replace `⏎······from,⏎······to,⏎······route⏎····)` with `from,·to,·route);`
from,
to,
route
)
const sponsorFeeAmount = await this.getAmountTo(
Currency.STX,
stxAmount,
from
)

Check failure on line 193 in src/alexSDK.ts

View workflow job for this annotation

GitHub Actions / build

Insert `;`
return getYAmountFromXAmount(
from,
to,
fromAmount - sponsorFeeAmount,
await this.getPools(),
await this.getContractId(),
customRoute
);
}

/**
* Perform a swap between two currencies using the specified route and amount.
*
Expand Down Expand Up @@ -194,6 +232,60 @@ export class AlexSDK {
);
}

/**
* Perform a swap between two currencies using the specified route and amount.
* Targetting sponsor tx.
*
* @param {string} stxAddress - The Stacks (STX) address to execute the swap from.
* @param {Currency} currencyX - The currency to swap from.
* @param {Currency} currencyY - The currency to swap to.
* @param {bigint} fromAmount - The amount of the source currency to swap.
* @param {bigint} minDy - The minimum amount of the destination currency to receive.
* @param {AMMRoute} [customRoute] - An optional custom route for the swap.
* @returns {Promise<TxToBroadCast>} - A promise that resolves to a TxToBroadCast object, representing the transaction to be broadcasted.
*/
async runSwapForSponsorTx(
stxAddress: string,
currencyX: Currency,
currencyY: Currency,
fromAmount: bigint,
minDy: bigint,
customRoute?: AMMRoute
): Promise<TxToBroadCast> {
const route = customRoute ?? await this.getRoute(currencyX, currencyY)

Check failure on line 255 in src/alexSDK.ts

View workflow job for this annotation

GitHub Actions / build

Replace `await·this.getRoute(currencyX,·currencyY)` with `(await·this.getRoute(currencyX,·currencyY));`
const stxAmount = await requiredStxAmountForSponsorTx(
currencyX,
currencyY,
route
)

Check failure on line 260 in src/alexSDK.ts

View workflow job for this annotation

GitHub Actions / build

Insert `;`
const sponsorFeeAmount = await this.getAmountTo(
Currency.STX,
stxAmount,
currencyX
)

Check failure on line 265 in src/alexSDK.ts

View workflow job for this annotation

GitHub Actions / build

Insert `;`
return runSponsoredSpotTx(
stxAddress,
currencyX,
currencyY,
fromAmount,
minDy,
sponsorFeeAmount,
await this.getPools(),
await this.getTokenInfos(),
customRoute
);
}

/**
* Broadcast a sponsored transaction.
*
* @param {string} tx - The signed sponsor transaction to be broadcast.
* @returns {Promise<string>} - A promise that resolves to the transaction ID.
*/
async broadcastSponsoredTx(tx: string): Promise<string> {
return broadcastSponsoredTx(tx)

Check failure on line 286 in src/alexSDK.ts

View workflow job for this annotation

GitHub Actions / build

Insert `;`
}

/**
* This function fetches the current price data for all supported tokens. It returns an object where
* the keys are the currency identifiers (as defined in the Currency enum) and the values are the corresponding prices in USD.
Expand Down
2 changes: 2 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
export const configs = {
CONTRACT_DEPLOYER: 'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM',
SPONSOR_TX_DEPLOYER: 'SP212Y5JKN59YP3GYG07K3S8W5SSGE4KH6B5STXER',
SDK_API_HOST: 'https://alex-sdk-api.alexlab.co',
BACKEND_API_HOST: 'https://api.alexgo.io',
STACKS_API_HOST: 'https://api.hiro.so',
READONLY_CALL_API_HOST: 'https://stacks-node.alexlab.co',
SPONSORED_TX_EXECUTOR: 'https://api.stxer.xyz/sponsor/execute',
};
88 changes: 88 additions & 0 deletions src/generated/smartContract/contract_Alex_sponsor-dex-v01.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import {
defineContract,
traitT,
uintT,
principalT,
responseSimpleT,
booleanT,
optionalT,
} from '../smartContractHelpers/codegenImport';

export const sponsorDexV01 = defineContract({
'sponsor-dex-v01': {
claim: {
input: [
{ name: 'token', type: traitT },
{ name: 'amount', type: uintT },
{ name: 'recipient', type: principalT },
],
output: responseSimpleT(booleanT),
mode: 'public',
},
'swap-helper': {
input: [
{ name: 'token-x', type: traitT },
{ name: 'token-y', type: traitT },
{ name: 'factor', type: uintT },
{ name: 'dx', type: uintT },
{ name: 'min-dy', type: optionalT(uintT) },
{ name: 'fee', type: uintT },
],
output: responseSimpleT(responseSimpleT(uintT)),
mode: 'public',
},
'swap-helper-a': {
input: [
{ name: 'token-x', type: traitT },
{ name: 'token-y', type: traitT },
{ name: 'token-z', type: traitT },
{ name: 'factor-x', type: uintT },
{ name: 'factor-y', type: uintT },
{ name: 'dx', type: uintT },
{ name: 'min-dz', type: optionalT(uintT) },
{ name: 'fee', type: uintT },
],
output: responseSimpleT(responseSimpleT(uintT)),
mode: 'public',
},
'swap-helper-b': {
input: [
{ name: 'token-x', type: traitT },
{ name: 'token-y', type: traitT },
{ name: 'token-z', type: traitT },
{ name: 'token-w', type: traitT },
{ name: 'factor-x', type: uintT },
{ name: 'factor-y', type: uintT },
{ name: 'factor-z', type: uintT },
{ name: 'dx', type: uintT },
{ name: 'min-dw', type: optionalT(uintT) },
{ name: 'fee', type: uintT },
],
output: responseSimpleT(responseSimpleT(uintT)),
mode: 'public',
},
'swap-helper-c': {
input: [
{ name: 'token-x', type: traitT },
{ name: 'token-y', type: traitT },
{ name: 'token-z', type: traitT },
{ name: 'token-w', type: traitT },
{ name: 'token-v', type: traitT },
{ name: 'factor-x', type: uintT },
{ name: 'factor-y', type: uintT },
{ name: 'factor-z', type: uintT },
{ name: 'factor-w', type: uintT },
{ name: 'dx', type: uintT },
{ name: 'min-dv', type: optionalT(uintT) },
{ name: 'fee', type: uintT },
],
output: responseSimpleT(responseSimpleT(uintT)),
mode: 'public',
},
'is-dao-or-extension': {
input: [],
output: responseSimpleT(booleanT),
mode: 'readonly',
},
},
} as const);
2 changes: 2 additions & 0 deletions src/generated/smartContract/contracts_Alex.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { defineContract } from '../smartContractHelpers/codegenImport';
import { ammPoolV201 } from './contract_Alex_amm-pool-v2-01';
import { sponsorDexV01 } from './contract_Alex_sponsor-dex-v01';

export const AlexContracts = defineContract({
...ammPoolV201,
...sponsorDexV01,
});
9 changes: 2 additions & 7 deletions src/helpers/RouteHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,13 @@ import type { Currency } from '../currency';
import type { PoolData } from '../types';
import {
type AMMRouteSegment,
resolveAmmRoute,
resolveAmmRoutes,
} from '../utils/ammRouteResolver';

export async function getAllPossibleRoute(
from: Currency,
to: Currency,
pools: PoolData[]
): Promise<AMMRouteSegment[][]> {
const ammRoute = resolveAmmRoute(from, to, pools);
if (ammRoute.length > 0) {
// TODO: add all possible routes later
return [ammRoute];
}
throw new Error("Can't find route");
return resolveAmmRoutes(from, to, pools);
}
Loading

0 comments on commit 921ab32

Please sign in to comment.