mirror of
https://github.com/alexgo-io/alex-sdk.git
synced 2026-04-29 18:26:02 +08:00
feat: add broadcastSponsoredTx
This commit is contained in:
@@ -91,6 +91,13 @@ Check if a transaction is a swap transaction from Alex
|
||||
function isAlexSwapTransaction(deployer: string, contractName: string, functionName: string): boolean;
|
||||
```
|
||||
|
||||
### broadcastSponsoredTx
|
||||
|
||||
Broadcast a sponsored transaction to Alex's sponsored tx services
|
||||
```javascript
|
||||
function broadcastSponsoredTx(txRaw: string): Promise<string>;
|
||||
````
|
||||
|
||||
## Installation
|
||||
|
||||
You can install Alex-SDK using npm:
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
import { fetchLatestPrices } from './utils/currencyPrice';
|
||||
import { assignConfig, AssignConfigParams, configs } from './config';
|
||||
import { AlexContracts } from './generated/smartContract/contracts_Alex';
|
||||
import { broadcastSponsoredTx } from './utils/sponsoredTx';
|
||||
|
||||
export class AlexSDK {
|
||||
static configure(config: AssignConfigParams) {
|
||||
@@ -96,4 +97,8 @@ export class AlexSDK {
|
||||
// @ts-ignore
|
||||
return AlexContracts[contractName][functionName] != null;
|
||||
}
|
||||
|
||||
broadcastSponsoredTx(txRaw: string): Promise<string> {
|
||||
return broadcastSponsoredTx(txRaw);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Currency } from './currency';
|
||||
const CONTRACT_DEPLOYER = 'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9';
|
||||
const API_HOST = 'https://stacks-blockchain-lb.alexlab.co';
|
||||
const IS_MAINNET = true;
|
||||
const SPONSORED_TX_EXECUTOR = 'https://sponsor-tx.alexlab.co/v1/graphql';
|
||||
|
||||
const NATIVE_TOKEN_MAPPING: {
|
||||
[P in Exclude<Currency, Currency.STX>]: {
|
||||
@@ -84,6 +85,7 @@ export const configs = {
|
||||
CONTRACT_DEPLOYER,
|
||||
API_HOST,
|
||||
NATIVE_TOKEN_MAPPING,
|
||||
SPONSORED_TX_EXECUTOR,
|
||||
};
|
||||
|
||||
type AlexConfig = typeof configs;
|
||||
|
||||
90
src/utils/sponsoredTx.ts
Normal file
90
src/utils/sponsoredTx.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
import { configs } from '../config';
|
||||
|
||||
export async function broadcastSponsoredTx(tx: string): Promise<string> {
|
||||
const response = await fetch(configs.SPONSORED_TX_EXECUTOR, {
|
||||
method: 'POST',
|
||||
mode: 'cors',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
query: `mutation run($tx:String!) {
|
||||
execute(tx:$tx)
|
||||
}`,
|
||||
variables: {
|
||||
tx,
|
||||
},
|
||||
}),
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(response.statusText);
|
||||
}
|
||||
const result = await response.json();
|
||||
if (result.data == null) {
|
||||
throw new Error(result.errors?.[0]?.message ?? 'Unknown Error');
|
||||
}
|
||||
const {
|
||||
data: { execute: txId },
|
||||
} = result;
|
||||
return await retry(() => tryToFetchTxId(txId), 10);
|
||||
}
|
||||
|
||||
async function tryToFetchTxId(txId: string): Promise<string | null> {
|
||||
const response = await fetch(configs.SPONSORED_TX_EXECUTOR, {
|
||||
method: 'POST',
|
||||
mode: 'cors',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
query: `query checkStatus($txId: bytea!) {
|
||||
user_operations(where:{tx_id:{_eq:$txId}}) {
|
||||
sponsor_tx_id
|
||||
error
|
||||
}
|
||||
}`,
|
||||
variables: {
|
||||
txId: hexAddressToHasuraAddress(txId),
|
||||
},
|
||||
}),
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(response.statusText);
|
||||
}
|
||||
const {
|
||||
data: { user_operations },
|
||||
} = await response.json();
|
||||
if (user_operations.length === 0) {
|
||||
return null;
|
||||
}
|
||||
const operation = user_operations[0];
|
||||
if (operation.error) {
|
||||
throw new Error(operation.error);
|
||||
} else if (operation.sponsor_tx_id) {
|
||||
return hasuraAddressToHex(operation.sponsor_tx_id);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async function retry<T>(
|
||||
action: () => Promise<T | null>,
|
||||
count = 10
|
||||
): Promise<T> {
|
||||
for (let i = 0; i < count; i++) {
|
||||
const result = await action();
|
||||
if (result === null) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
continue;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
throw new Error('Timeout waiting for response');
|
||||
}
|
||||
|
||||
export function hexAddressToHasuraAddress(input: string): string {
|
||||
return '\\x' + input;
|
||||
}
|
||||
|
||||
export function hasuraAddressToHex(input: string): string {
|
||||
return input.replace(/\\x/, '0x').toLowerCase();
|
||||
}
|
||||
Reference in New Issue
Block a user