@perawallet/swap
Version:
Algorand swap utilities and widget integration
293 lines (286 loc) • 8.13 kB
JavaScript
;
var algosdk = require('algosdk');
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
var algosdk__default = /*#__PURE__*/_interopDefault(algosdk);
// src/utils.ts
async function makeRequest(baseURL, endpoint, options = {}) {
const url = `${baseURL}${endpoint}`;
const response = await fetch(url, {
headers: {
"Content-Type": "application/json",
...options.headers
},
...options
});
if (!response.ok) {
let errorDetails = "";
try {
errorDetails = await response.json();
} catch {
try {
errorDetails = await response.text();
} catch {
errorDetails = "Unable to read error details";
}
}
throw new Error(JSON.stringify(errorDetails));
}
return response.json();
}
function getPeraBaseUrl(network) {
return network === "mainnet" ? "https://mainnet.api.perawallet.app" : "https://testnet.api.perawallet.app";
}
var DEFAULT_WIDGET_URL = "https://swap-widget.perawallet.app";
// src/swap.ts
var PeraSwap = class {
constructor(network = "mainnet", referrerUrl) {
this.network = network;
this.baseURL = getPeraBaseUrl(network);
this.referrerUrl = referrerUrl;
}
/**
* Update the network for all subsequent operations
*/
updateNetwork(network) {
this.network = network;
this.baseURL = getPeraBaseUrl(network);
}
/**
* Get the current network
*/
getNetwork() {
return this.network;
}
/**
* Create a swap quote
*/
async createQuote(body, signal) {
const bodyData = {
...body,
referrer_url: this.referrerUrl
};
return makeRequest(this.baseURL, "/v2/dex-swap/quotes/", {
method: "POST",
body: JSON.stringify(bodyData),
signal
});
}
/**
* Update the status of a swap
*/
async updateSwapStatus(swapId, body) {
const bodyData = {
...body,
platform: "js-sdk",
swap_version: "v2"
};
return makeRequest(this.baseURL, `/v2/dex-swap/swaps/${swapId}/`, {
method: "PATCH",
body: JSON.stringify(bodyData)
});
}
/**
* Prepare transactions for a swap
*/
async prepareTransactions(quoteId, depositAddress) {
return makeRequest(
this.baseURL,
`/v2/dex-swap/prepare-transactions/`,
{
method: "POST",
body: JSON.stringify({
quote: quoteId,
deposit_address: depositAddress
})
}
);
}
/**
* Get available assets for swapping
*/
async getAvailableAssets(params) {
const searchParams = new URLSearchParams();
searchParams.append("asset_in_id", params.asset_in_id.toString());
if (params.q) searchParams.append("q", params.q);
return makeRequest(this.baseURL, `/v1/dex-swap/available-assets/?${searchParams}`);
}
/**
* Get assets by IDs or search query
*/
async getAssets(params) {
const searchParams = new URLSearchParams();
if (params.asset_ids) searchParams.append("asset_ids", params.asset_ids.join(","));
if (params.q) searchParams.append("q", params.q);
return makeRequest(this.baseURL, `/v1/assets/?${searchParams}`);
}
/**
* Get ALGO price in USD
*/
async getAlgoPrice() {
return makeRequest(this.baseURL, "/v1/currencies/USD/");
}
/**
* Get asset information by ID
*/
async getAsset(assetId) {
try {
const response = await this.getAssets({ asset_ids: [assetId.toString()] });
return response.results[0] || null;
} catch (error) {
console.error("Error fetching asset:", error);
return null;
}
}
/**
* Search for assets by name
*/
async searchAssets(query) {
try {
const response = await this.getAssets({ q: query });
return response.results;
} catch (error) {
console.error("Error searching assets:", error);
return [];
}
}
};
// src/types.ts
var SwapWidgetSearchParamKey = /* @__PURE__ */ ((SwapWidgetSearchParamKey2) => {
SwapWidgetSearchParamKey2["USE_PARENT_SIGNER"] = "useParentSigner";
SwapWidgetSearchParamKey2["ACCOUNT_ADDRESS"] = "accountAddress";
SwapWidgetSearchParamKey2["NETWORK"] = "network";
SwapWidgetSearchParamKey2["THEME"] = "theme";
SwapWidgetSearchParamKey2["ASSET_IN"] = "assetIn";
SwapWidgetSearchParamKey2["ASSET_OUT"] = "assetOut";
SwapWidgetSearchParamKey2["IFRAME_BACKGROUND"] = "iframeBg";
return SwapWidgetSearchParamKey2;
})(SwapWidgetSearchParamKey || {});
var WidgetController = class _WidgetController {
constructor(config = {}) {
this.config = config;
}
/**
* Generate a URL for the Pera Swap Widget iframe
*/
static generateWidgetUrl(config = {}) {
const url = new URL(DEFAULT_WIDGET_URL);
if (config.network) {
url.searchParams.set("network", config.network);
}
if (config.theme) {
url.searchParams.set("theme", config.theme);
}
if (config.assetIn !== void 0) {
url.searchParams.set("assetIn", String(config.assetIn));
}
if (config.assetOut !== void 0) {
url.searchParams.set("assetOut", String(config.assetOut));
}
if (config.iframeBg) {
url.searchParams.set("iframeBg", config.iframeBg);
}
if (config.useParentSigner) {
url.searchParams.set("useParentSigner", "true");
if (config.accountAddress) {
url.searchParams.set("accountAddress", config.accountAddress);
}
}
return url.toString();
}
/**
* Create an iframe element with the swap widget
*/
static createWidgetIframe(config = {}, options = {}) {
const iframe = document.createElement("iframe");
iframe.src = _WidgetController.generateWidgetUrl(config);
iframe.width = options.width || "100%";
iframe.height = options.height || "488px";
if (options.className) {
iframe.className = options.className;
}
if (options.id) {
iframe.id = options.id;
}
return iframe;
}
/**
* Send message to widget iframe
*/
static sendMessageToWidget({
data,
targetWindow
}) {
if (targetWindow) {
targetWindow.postMessage(data, "*");
}
}
/**
* Add event listeners for widget communication
*/
addWidgetEventListeners() {
window.addEventListener("message", this.handleMessage.bind(this));
}
/**
* Remove event listeners
*/
removeWidgetEventListeners() {
window.removeEventListener("message", this.handleMessage.bind(this));
}
/**
* Handle messages from the widget
*/
handleMessage(event) {
if (!event.data || !event.data.type || !event.data.message) {
return;
}
switch (event.data.type) {
case "TXN_SIGN_REQUEST": {
const { txGroups } = event.data.message;
const decodedTxGroups = txGroups.map(
(group) => group.map((bytes) => algosdk__default.default.decodeUnsignedTransaction(bytes))
);
if (this.config.onTxnSignRequest) {
this.config.onTxnSignRequest({ txGroups: decodedTxGroups }).then((signedTxns) => {
_WidgetController.sendMessageToWidget({
data: {
message: {
type: "TXN_SIGN_RESPONSE",
signedTxns
}
},
targetWindow: event.source
});
}).catch((error) => {
_WidgetController.sendMessageToWidget({
data: {
message: {
type: "FAILED_TXN_SIGN",
error
}
},
targetWindow: event.source
});
});
}
break;
}
case "TXN_SIGN_REQUEST_TIMEOUT": {
if (this.config.onTxnSignRequestTimeout) {
this.config.onTxnSignRequestTimeout();
}
break;
}
case "SWAP_SUCCESS": {
if (this.config.onSwapSuccess) {
this.config.onSwapSuccess(event.data.message);
}
break;
}
}
}
};
exports.PeraSwap = PeraSwap;
exports.SwapWidgetSearchParamKey = SwapWidgetSearchParamKey;
exports.WidgetController = WidgetController;
//# sourceMappingURL=index.js.map
//# sourceMappingURL=index.js.map