explorer: add Bonfida Bots instructions (#16872)

* explorer: add Bonfida Bots instructions

* Update explorer/src/components/instruction/BonfidaBotDetails.tsx

Co-authored-by: Josh <josh.hundley@gmail.com>

* explorer: Bonfida Bot instructions fixes

Co-authored-by: Josh <josh.hundley@gmail.com>
This commit is contained in:
DR497 2021-04-30 06:47:10 +08:00 committed by GitHub
parent 5981399612
commit 0ef5a9b1d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 1541 additions and 4 deletions

View File

@ -1270,6 +1270,49 @@
"resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-10.1.0.tgz",
"integrity": "sha512-ij4wRiunFfaJxjB0BdrYHIH8FxBJpOwNPhhAcunlmPdXudL1WQV1qoP9un6JsEBAgQH+7UXyyjh0g7jTxXK6tg=="
},
"@dr497/awesome-serum-markets": {
"version": "1.1.31",
"resolved": "https://registry.npmjs.org/@dr497/awesome-serum-markets/-/awesome-serum-markets-1.1.31.tgz",
"integrity": "sha512-DGI/WOChZ7oQdaD3o1KfqW7E2yeYsGLD0MMocHQFVMH/2Vi5agj50XezO8QIrRsDw2F4ZMQSOKIZ03XiRXsvSQ==",
"requires": {
"@solana/web3.js": "^0.87.1"
},
"dependencies": {
"@solana/web3.js": {
"version": "0.87.2",
"resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-0.87.2.tgz",
"integrity": "sha512-BtrOGfg7zUud/zLL/BxXV3E84qpXK1HknqncNQDNr8JlJ4tGc+Xsip5DzSMP/fNUJgbAWblHqWWJxFdN2mtO6A==",
"requires": {
"@babel/runtime": "^7.3.1",
"bn.js": "^5.0.0",
"bs58": "^4.0.1",
"buffer": "^6.0.1",
"buffer-layout": "^1.2.0",
"crypto-hash": "^1.2.2",
"esdoc-inject-style-plugin": "^1.0.0",
"jayson": "^3.0.1",
"keccak": "^3.0.1",
"mz": "^2.7.0",
"node-fetch": "^2.2.0",
"npm-run-all": "^4.1.5",
"rpc-websockets": "^7.4.2",
"secp256k1": "^4.0.2",
"superstruct": "^0.8.3",
"tweetnacl": "^1.0.0",
"ws": "^7.0.0"
}
},
"superstruct": {
"version": "0.8.4",
"resolved": "https://registry.npmjs.org/superstruct/-/superstruct-0.8.4.tgz",
"integrity": "sha512-48Ors8IVWZm/tMr8r0Si6+mJiB7mkD7jqvIzktjJ4+EnP5tBp0qOpiM1J8sCUorKx+TXWrfb3i1UcjdD1YK/wA==",
"requires": {
"kind-of": "^6.0.2",
"tiny-invariant": "^1.0.6"
}
}
}
},
"@emotion/cache": {
"version": "11.1.3",
"resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.1.3.tgz",
@ -2483,6 +2526,15 @@
}
}
},
"@project-serum/sol-wallet-adapter": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/@project-serum/sol-wallet-adapter/-/sol-wallet-adapter-0.1.8.tgz",
"integrity": "sha512-lKMgp7bsKpkrtBtIaEjtGuUMke0GUqFUL39Z7cjqsQpTVhkU5Ez4zHyjhXqAEORRGLFbwx/+H6HLpwppxpUDMQ==",
"requires": {
"bs58": "^4.0.1",
"eventemitter3": "^4.0.4"
}
},
"@react-hook/debounce": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@react-hook/debounce/-/debounce-3.0.0.tgz",
@ -2627,6 +2679,68 @@
"@sinonjs/commons": "^1.7.0"
}
},
"@solana/spl-token": {
"version": "0.0.13",
"resolved": "https://registry.npmjs.org/@solana/spl-token/-/spl-token-0.0.13.tgz",
"integrity": "sha512-WT8M9V/hxURR5jLbhr3zgwVsgcY6m8UhHtK045w7o+jx8FJ9MKARkj387WBFU7mKiFq0k8jw/8YL7XmnIUuH8Q==",
"requires": {
"@babel/runtime": "^7.10.5",
"@solana/web3.js": "^0.86.1",
"bn.js": "^5.0.0",
"buffer-layout": "^1.2.0",
"dotenv": "8.2.0",
"mkdirp": "1.0.4"
},
"dependencies": {
"@solana/web3.js": {
"version": "0.86.4",
"resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-0.86.4.tgz",
"integrity": "sha512-FpabDmdyxBN5aHIVUWc9Q6pXJFWiLRm/xeyxFg9O9ICHjiUkd38omds7G0CAmykIccG7zaMziwtkXp+0KvQOhA==",
"requires": {
"@babel/runtime": "^7.3.1",
"bn.js": "^5.0.0",
"bs58": "^4.0.1",
"buffer": "^5.4.3",
"buffer-layout": "^1.2.0",
"crypto-hash": "^1.2.2",
"esdoc-inject-style-plugin": "^1.0.0",
"jayson": "^3.0.1",
"keccak": "^3.0.1",
"mz": "^2.7.0",
"node-fetch": "^2.2.0",
"npm-run-all": "^4.1.5",
"rpc-websockets": "^7.4.2",
"secp256k1": "^4.0.2",
"superstruct": "^0.8.3",
"tweetnacl": "^1.0.0",
"ws": "^7.0.0"
}
},
"buffer": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
"requires": {
"base64-js": "^1.3.1",
"ieee754": "^1.1.13"
}
},
"mkdirp": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="
},
"superstruct": {
"version": "0.8.4",
"resolved": "https://registry.npmjs.org/superstruct/-/superstruct-0.8.4.tgz",
"integrity": "sha512-48Ors8IVWZm/tMr8r0Si6+mJiB7mkD7jqvIzktjJ4+EnP5tBp0qOpiM1J8sCUorKx+TXWrfb3i1UcjdD1YK/wA==",
"requires": {
"kind-of": "^6.0.2",
"tiny-invariant": "^1.0.6"
}
}
}
},
"@solana/spl-token-registry": {
"version": "0.2.64",
"resolved": "https://registry.npmjs.org/@solana/spl-token-registry/-/spl-token-registry-0.2.64.tgz",
@ -4769,11 +4883,31 @@
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
"optional": true,
"requires": {
"file-uri-to-path": "1.0.0"
}
},
"bip32": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/bip32/-/bip32-2.0.6.tgz",
"integrity": "sha512-HpV5OMLLGTjSVblmrtYRfFFKuQB+GArM0+XP8HGWfJ5vxYBqo+DesvJwOdC2WJ3bCkZShGf0QIfoIpeomVzVdA==",
"requires": {
"@types/node": "10.12.18",
"bs58check": "^2.1.1",
"create-hash": "^1.2.0",
"create-hmac": "^1.1.7",
"tiny-secp256k1": "^1.1.3",
"typeforce": "^1.11.5",
"wif": "^2.0.6"
},
"dependencies": {
"@types/node": {
"version": "10.12.18",
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz",
"integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ=="
}
}
},
"block-stream": {
"version": "0.0.9",
"resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
@ -4821,6 +4955,58 @@
}
}
},
"bonfida-bot": {
"version": "0.4.9",
"resolved": "https://registry.npmjs.org/bonfida-bot/-/bonfida-bot-0.4.9.tgz",
"integrity": "sha512-gPOaQl1rFeazoteSj2PpyrRDlp4A9AuKtg7drRrm7W+DWe73p902KAs76Vs3XlS+aQjF2kWlSLqBGsC79iijgA==",
"requires": {
"@dr497/awesome-serum-markets": "^1.1.16",
"@project-serum/serum": "^0.13.30",
"@project-serum/sol-wallet-adapter": "^0.1.5",
"@solana/spl-token": "0.0.13",
"@solana/web3.js": "^0.94.2",
"bip32": "^2.0.6",
"bn.js": "^5.1.3",
"bs58": "4.0.1",
"buffer-layout": "^1.2.0",
"tweetnacl": "^1.0.3"
},
"dependencies": {
"@babel/runtime": {
"version": "7.13.17",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.17.tgz",
"integrity": "sha512-NCdgJEelPTSh+FEFylhnP1ylq848l1z9t9N0j1Lfbcw0+KXGjsTvUmkxy+voLLXB5SOKMbLLx4jxYliGrYQseA==",
"requires": {
"regenerator-runtime": "^0.13.4"
}
},
"@solana/web3.js": {
"version": "0.94.2",
"resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-0.94.2.tgz",
"integrity": "sha512-enJZ9eVJMvNtpuXdygAZHBlPC+2Q3paLY+KforFhVUpi/bkBADDKJWd90RICyu3sPKiVt8YLAs9cIxriQpQqng==",
"requires": {
"@babel/runtime": "^7.12.5",
"bn.js": "^5.0.0",
"bs58": "^4.0.1",
"buffer": "6.0.1",
"buffer-layout": "^1.2.0",
"crypto-hash": "^1.2.2",
"jayson": "^3.4.4",
"js-sha3": "^0.8.0",
"node-fetch": "^2.6.1",
"rpc-websockets": "^7.4.2",
"secp256k1": "^4.0.2",
"superstruct": "^0.14.2",
"tweetnacl": "^1.0.0"
}
},
"superstruct": {
"version": "0.14.2",
"resolved": "https://registry.npmjs.org/superstruct/-/superstruct-0.14.2.tgz",
"integrity": "sha512-nPewA6m9mR3d6k7WkZ8N8zpTWfenFH3q9pA2PkuiZxINr9DKB2+40wEQf0ixn8VaGuJ78AB6iWOtStI+/4FKZQ=="
}
}
},
"bonjour": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz",
@ -4958,6 +5144,16 @@
"base-x": "^3.0.2"
}
},
"bs58check": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz",
"integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==",
"requires": {
"bs58": "^4.0.0",
"create-hash": "^1.1.0",
"safe-buffer": "^5.1.2"
}
},
"bser": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz",
@ -8055,8 +8251,7 @@
"file-uri-to-path": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
"optional": true
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="
},
"filesize": {
"version": "6.1.0",
@ -18218,6 +18413,25 @@
"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz",
"integrity": "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw=="
},
"tiny-secp256k1": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-1.1.6.tgz",
"integrity": "sha512-FmqJZGduTyvsr2cF3375fqGHUovSwDi/QytexX1Se4BPuPZpTE5Ftp5fg+EFSuEf3lhZqgCRjEG3ydUQ/aNiwA==",
"requires": {
"bindings": "^1.3.0",
"bn.js": "^4.11.8",
"create-hmac": "^1.1.7",
"elliptic": "^6.4.0",
"nan": "^2.13.2"
},
"dependencies": {
"bn.js": {
"version": "4.12.0",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="
}
}
},
"tiny-warning": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
@ -18417,6 +18631,11 @@
"is-typedarray": "^1.0.0"
}
},
"typeforce": {
"version": "1.18.0",
"resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz",
"integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g=="
},
"typescript": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz",
@ -19766,6 +19985,14 @@
"string-width": "^1.0.2 || 2"
}
},
"wif": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/wif/-/wif-2.0.6.tgz",
"integrity": "sha1-CNP1IFbGZnkplyb63g1DKudLRwQ=",
"requires": {
"bs58check": "<3.0.0"
}
},
"word-wrap": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",

View File

@ -26,6 +26,7 @@
"@types/socket.io-client": "^1.4.36",
"bignumber.js": "^9.0.1",
"bn.js": "^5.2.0",
"bonfida-bot": "^0.4.9",
"bootstrap": "^4.6.0",
"bs58": "^4.0.1",
"chai": "^4.3.4",

View File

@ -39,6 +39,10 @@ import {
isSerumInstruction,
parseSerumInstructionTitle,
} from "components/instruction/serum/types";
import {
isBonfidaBotInstruction,
parseBonfidaBotInstructionTitle,
} from "components/instruction/bonfida-bot/types";
import { INNER_INSTRUCTIONS_START_SLOT } from "pages/TransactionDetailsPage";
import { useCluster, Cluster } from "providers/cluster";
import { Link } from "react-router-dom";
@ -488,6 +492,16 @@ const TokenTransactionRow = React.memo(
reportError(error, { signature: tx.signature });
return undefined;
}
} else if (
transactionInstruction &&
isBonfidaBotInstruction(transactionInstruction)
) {
try {
name = parseBonfidaBotInstructionTitle(transactionInstruction);
} catch (error) {
reportError(error, { signature: tx.signature });
return undefined;
}
} else {
if (
ix.accounts.findIndex((account) =>

View File

@ -0,0 +1,92 @@
import React from "react";
import { TransactionInstruction, SignatureResult } from "@solana/web3.js";
import { InstructionCard } from "./InstructionCard";
import { useCluster } from "providers/cluster";
import { reportError } from "utils/sentry";
import {
decodeCancelOrder,
decodeInitializeBot,
decodeCreateBot,
decodeDeposit,
decodeCreateOrder,
decodeSettleFunds,
decodeRedeem,
decodeCollectFees,
parseBonfidaBotInstructionTitle,
} from "./bonfida-bot/types";
import { CancelOrderDetailsCard } from "./bonfida-bot/CancelOrderDetails";
import { CollectFeesDetailsCard } from "./bonfida-bot/CollectFeesDetails";
import { CreateBotDetailsCard } from "./bonfida-bot/CreateBotDetails";
import { DepositDetailsCard } from "./bonfida-bot/DepositDetails";
import { InitializeBotDetailsCard } from "./bonfida-bot/InitializeBotDetails";
import { RedeemDetailsCard } from "./bonfida-bot/RedeemDetails";
import { SettleFundsDetailsCard } from "./bonfida-bot/SettleFundsDetails";
import { CreateOrderDetailsCard } from "./bonfida-bot/CreateOrderDetails";
export function BonfidaBotDetailsCard(props: {
ix: TransactionInstruction;
index: number;
result: SignatureResult;
signature: string;
innerCards?: JSX.Element[];
childIndex?: number;
}) {
const { ix, index, result, signature, innerCards, childIndex } = props;
const { url } = useCluster();
let title;
try {
title = parseBonfidaBotInstructionTitle(ix);
switch (title) {
case "Initialize Bot":
return (
<InitializeBotDetailsCard info={decodeInitializeBot(ix)} {...props} />
);
case "Create Bot":
return <CreateBotDetailsCard info={decodeCreateBot(ix)} {...props} />;
case "Deposit":
return <DepositDetailsCard info={decodeDeposit(ix)} {...props} />;
case "Create Order":
return (
<CreateOrderDetailsCard info={decodeCreateOrder(ix)} {...props} />
);
case "Cancel Order":
return (
<CancelOrderDetailsCard info={decodeCancelOrder(ix)} {...props} />
);
case "Settle Funds":
return (
<SettleFundsDetailsCard info={decodeSettleFunds(ix)} {...props} />
);
case "settleFunds":
return (
<SettleFundsDetailsCard info={decodeSettleFunds(ix)} {...props} />
);
case "Redeem":
return <RedeemDetailsCard info={decodeRedeem(ix)} {...props} />;
case "Collect Fees":
return (
<CollectFeesDetailsCard info={decodeCollectFees(ix)} {...props} />
);
}
} catch (error) {
reportError(error, {
url: url,
signature: signature,
});
}
return (
<InstructionCard
ix={ix}
index={index}
result={result}
title={`Bonfida Bot: ${title || "Unknown"}`}
innerCards={innerCards}
childIndex={childIndex}
defaultRaw
/>
);
}

View File

@ -0,0 +1,105 @@
import React from "react";
import { SignatureResult, TransactionInstruction } from "@solana/web3.js";
import { InstructionCard } from "../InstructionCard";
import { Address } from "components/common/Address";
import { CancelOrder } from "./types";
export function CancelOrderDetailsCard(props: {
ix: TransactionInstruction;
index: number;
result: SignatureResult;
info: CancelOrder;
innerCards?: JSX.Element[];
childIndex?: number;
}) {
const { ix, index, result, info, innerCards, childIndex } = props;
return (
<InstructionCard
ix={ix}
index={index}
result={result}
title="Serum: Cancel Order"
innerCards={innerCards}
childIndex={childIndex}
>
<tr>
<td>Program</td>
<td className="text-lg-right">
<Address pubkey={info.programId} alignRight link />
</td>
</tr>
<tr>
<td>Market</td>
<td className="text-lg-right">
<Address pubkey={info.market} alignRight link />
</td>
</tr>
<tr>
<td>Signal Provider Address</td>
<td className="text-lg-right">
<Address pubkey={info.signalProviderKey} alignRight link />
</td>
</tr>
<tr>
<td>Open Orders</td>
<td className="text-lg-right">
<Address pubkey={info.openOrdersKey} alignRight link />
</td>
</tr>
<tr>
<td>Serum Event Queue</td>
<td className="text-lg-right">
<Address pubkey={info.serumEventQueue} alignRight link />
</td>
</tr>
<tr>
<td>Serum Bids</td>
<td className="text-lg-right">
<Address pubkey={info.serumMarketBids} alignRight link />
</td>
</tr>
<tr>
<td>Serum Asks</td>
<td className="text-lg-right">
<Address pubkey={info.serumMarketAsks} alignRight link />
</td>
</tr>
<tr>
<td>Bot Address</td>
<td className="text-lg-right">
<Address pubkey={info.poolKey} alignRight link />
</td>
</tr>
<tr>
<td>Serum Program ID</td>
<td className="text-lg-right">
<Address pubkey={info.dexProgramKey} alignRight link />
</td>
</tr>
<tr>
<td>Pool Seed</td>
<td className="text-lg-right">{info.poolSeed}</td>
</tr>
<tr>
<td>Side</td>
<td className="text-lg-right">{info.side}</td>
</tr>
<tr>
<td>Order Id</td>
<td className="text-lg-right">{info.orderId.toString(10)}</td>
</tr>
</InstructionCard>
);
}

View File

@ -0,0 +1,60 @@
import React from "react";
import { SignatureResult, TransactionInstruction } from "@solana/web3.js";
import { InstructionCard } from "../InstructionCard";
import { Address } from "components/common/Address";
import { CollectFees } from "./types";
export function CollectFeesDetailsCard(props: {
ix: TransactionInstruction;
index: number;
result: SignatureResult;
info: CollectFees;
innerCards?: JSX.Element[];
childIndex?: number;
}) {
const { ix, index, result, info, innerCards, childIndex } = props;
return (
<InstructionCard
ix={ix}
index={index}
result={result}
title="Bonfida Bot: Collect Fees"
innerCards={innerCards}
childIndex={childIndex}
>
<tr>
<td>Program</td>
<td className="text-lg-right">
<Address pubkey={info.programId} alignRight link />
</td>
</tr>
<tr>
<td>Signal Provider</td>
<td className="text-lg-right">
<Address pubkey={info.signalProviderPoolTokenKey} alignRight link />
</td>
</tr>
<tr>
<td>Insurance Fund</td>
<td className="text-lg-right">
<Address pubkey={info.bonfidaFeePoolTokenKey} alignRight link />
</td>
</tr>
<tr>
<td>Buy and Burn</td>
<td className="text-lg-right">
<Address pubkey={info.bonfidaBnBPTKey} alignRight link />
</td>
</tr>
<tr>
<td>Pool Seed</td>
<td className="text-lg-right">{info.poolSeed}</td>
</tr>
</InstructionCard>
);
}

View File

@ -0,0 +1,94 @@
import React from "react";
import { SignatureResult, TransactionInstruction } from "@solana/web3.js";
import { InstructionCard } from "../InstructionCard";
import { Address } from "components/common/Address";
import { CreateBot } from "./types";
export function CreateBotDetailsCard(props: {
ix: TransactionInstruction;
index: number;
result: SignatureResult;
info: CreateBot;
innerCards?: JSX.Element[];
childIndex?: number;
}) {
const { ix, index, result, info, innerCards, childIndex } = props;
return (
<InstructionCard
ix={ix}
index={index}
result={result}
title="Bonfida Bot: Create Bot"
innerCards={innerCards}
childIndex={childIndex}
>
<tr>
<td>Program</td>
<td className="text-lg-right">
<Address pubkey={info.programId} alignRight link />
</td>
</tr>
<tr>
<td>Bot Token Mint</td>
<td className="text-lg-right">
<Address pubkey={info.mintKey} alignRight link />
</td>
</tr>
<tr>
<td>Bot Address</td>
<td className="text-lg-right">
<Address pubkey={info.poolKey} alignRight link />
</td>
</tr>
<tr>
<td>Target Pool Token Address</td>
<td className="text-lg-right">
<Address pubkey={info.targetPoolTokenKey} alignRight link />
</td>
</tr>
<tr>
<td>Serum Program ID</td>
<td className="text-lg-right">
<Address pubkey={info.serumProgramId} alignRight link />
</td>
</tr>
<tr>
<td>Signal Provider Address</td>
<td className="text-lg-right">
<Address pubkey={info.signalProviderKey} alignRight link />
</td>
</tr>
<tr>
<td>Pool Seed</td>
<td className="text-lg-right">{info.poolSeed}</td>
</tr>
<tr>
<td>Fee Ratio</td>
<td className="text-lg-right">{info.feeRatio}</td>
</tr>
<tr>
<td>Fee Collection Period</td>
<td className="text-lg-right">{info.feeCollectionPeriod}</td>
</tr>
<tr>
<td>Serum Markets</td>
<td className="text-lg-right">{info.markets}</td>
</tr>
<tr>
<td>Deposit Amounts</td>
<td className="text-lg-right">{info.depositAmounts}</td>
</tr>
</InstructionCard>
);
}

View File

@ -0,0 +1,164 @@
import React from "react";
import {
SignatureResult,
TransactionInstruction,
PublicKey,
} from "@solana/web3.js";
import { InstructionCard } from "../InstructionCard";
import { Address } from "components/common/Address";
import { CreateOrder } from "./types";
export function CreateOrderDetailsCard(props: {
ix: TransactionInstruction;
index: number;
result: SignatureResult;
info: CreateOrder;
innerCards?: JSX.Element[];
childIndex?: number;
}) {
const { ix, index, result, info, innerCards, childIndex } = props;
console.log("Test");
return (
<InstructionCard
ix={ix}
index={index}
result={result}
title="Bonfida Bot: Create Order"
innerCards={innerCards}
childIndex={childIndex}
>
<tr>
<td>Program</td>
<td className="text-lg-right">
<Address pubkey={info.programId} alignRight link />
</td>
</tr>
<tr>
<td>Signal Provider Address</td>
<td className="text-lg-right">
<Address pubkey={info.signalProviderKey} alignRight link />
</td>
</tr>
<tr>
<td>Market</td>
<td className="text-lg-right">
<Address pubkey={info.market} alignRight link />
</td>
</tr>
<tr>
<td>Payer Bot Asset Address</td>
<td className="text-lg-right">
<Address pubkey={info.payerPoolAssetKey} alignRight link />
</td>
</tr>
<tr>
<td>Open Order</td>
<td className="text-lg-right">
<Address pubkey={info.openOrdersKey} alignRight link />
</td>
</tr>
<tr>
<td>Serum Request Queue</td>
<td className="text-lg-right">
<Address pubkey={info.serumRequestQueue} alignRight link />
</td>
</tr>
<tr>
<td>Serum Event Queue</td>
<td className="text-lg-right">
<Address pubkey={info.serumEventQueue} alignRight link />
</td>
</tr>
<tr>
<td>Serum Bids</td>
<td className="text-lg-right">
<Address pubkey={info.serumMarketBids} alignRight link />
</td>
</tr>
<tr>
<td>Serum Asks</td>
<td className="text-lg-right">
<Address pubkey={info.serumMarketAsks} alignRight link />
</td>
</tr>
<tr>
<td>Bot Address</td>
<td className="text-lg-right">
<Address pubkey={info.poolKey} alignRight link />
</td>
</tr>
<tr>
<td>Coin Vault</td>
<td className="text-lg-right">
<Address pubkey={info.coinVaultKey} alignRight link />
</td>
</tr>
<tr>
<td>Pc Vault</td>
<td className="text-lg-right">
<Address pubkey={info.pcVaultKey} alignRight link />
</td>
</tr>
<tr>
<td>Serum Program ID</td>
<td className="text-lg-right">
<Address pubkey={info.dexProgramKey} alignRight link />
</td>
</tr>
<tr>
<td>Bot Token Mint</td>
<td className="text-lg-right">
<Address pubkey={new PublicKey(info.targetMint)} alignRight link />
</td>
</tr>
<tr>
<td>Pool Seed</td>
<td className="text-lg-right">{info.poolSeed}</td>
</tr>
<tr>
<td>Side</td>
<td className="text-lg-right">{info.side}</td>
</tr>
<tr>
<td>Limit Price</td>
<td className="text-lg-right">{info.limitPrice}</td>
</tr>
<tr>
<td>Ratio to Trade</td>
<td className="text-lg-right">{info.ratioOfPoolAssetsToTrade}</td>
</tr>
<tr>
<td>Order Type</td>
<td className="text-lg-right">{info.orderType}</td>
</tr>
<tr>
<td>Coin Lot Size</td>
<td className="text-lg-right">{info.coinLotSize.toString()}</td>
</tr>
<tr>
<td>Pc Lot Size</td>
<td className="text-lg-right">{info.pcLotSize.toString()}</td>
</tr>
</InstructionCard>
);
}

View File

@ -0,0 +1,86 @@
import React from "react";
import { SignatureResult, TransactionInstruction } from "@solana/web3.js";
import { InstructionCard } from "../InstructionCard";
import { Address } from "components/common/Address";
import { Deposit } from "./types";
export function DepositDetailsCard(props: {
ix: TransactionInstruction;
index: number;
result: SignatureResult;
info: Deposit;
innerCards?: JSX.Element[];
childIndex?: number;
}) {
const { ix, index, result, info, innerCards, childIndex } = props;
return (
<InstructionCard
ix={ix}
index={index}
result={result}
title="Bonfida Bot: Deposit"
innerCards={innerCards}
childIndex={childIndex}
>
<tr>
<td>Program</td>
<td className="text-lg-right">
<Address pubkey={info.programId} alignRight link />
</td>
</tr>
<tr>
<td>Signal Provider Fee Address</td>
<td className="text-lg-right">
<Address pubkey={info.sigProviderFeeReceiverKey} alignRight link />
</td>
</tr>
<tr>
<td>Insurance Funds</td>
<td className="text-lg-right">
<Address pubkey={info.bonfidaFeeReceiverKey} alignRight link />
</td>
</tr>
<tr>
<td>Buy and Burn</td>
<td className="text-lg-right">
<Address pubkey={info.bonfidaBuyAndBurnKey} alignRight link />
</td>
</tr>
<tr>
<td>Bot Token Mint</td>
<td className="text-lg-right">
<Address pubkey={info.mintKey} alignRight link />
</td>
</tr>
<tr>
<td>Bot Address</td>
<td className="text-lg-right">
<Address pubkey={info.poolKey} alignRight link />
</td>
</tr>
<tr>
<td>Target Pool Token Address</td>
<td className="text-lg-right">
<Address pubkey={info.targetPoolTokenKey} alignRight link />
</td>
</tr>
<tr>
<td>Pool Seed</td>
<td className="text-lg-right">{info.poolSeed}</td>
</tr>
<tr>
<td>Pool Token Amount</td>
<td className="text-lg-right">{info.poolTokenAmount.toString()}</td>
</tr>
</InstructionCard>
);
}

View File

@ -0,0 +1,63 @@
import React from "react";
import { SignatureResult, TransactionInstruction } from "@solana/web3.js";
import { InstructionCard } from "../InstructionCard";
import { Address } from "components/common/Address";
import { InitializeBot } from "./types";
export function InitializeBotDetailsCard(props: {
ix: TransactionInstruction;
index: number;
result: SignatureResult;
info: InitializeBot;
innerCards?: JSX.Element[];
childIndex?: number;
}) {
const { ix, index, result, info, innerCards, childIndex } = props;
return (
<InstructionCard
ix={ix}
index={index}
result={result}
title="Bonfida Bot: Initialize Bot"
innerCards={innerCards}
childIndex={childIndex}
>
<tr>
<td>Program</td>
<td className="text-lg-right">
<Address pubkey={info.programId} alignRight link />
</td>
</tr>
<tr>
<td>Pool Account</td>
<td className="text-lg-right">
<Address pubkey={info.poolAccount} alignRight link />
</td>
</tr>
<tr>
<td>Mint Account</td>
<td className="text-lg-right">
<Address pubkey={info.mintAccount} alignRight link />
</td>
</tr>
<tr>
<td>Pool Seed</td>
<td className="text-lg-right">{info.poolSeed}</td>
</tr>
<tr>
<td>Max Number of Assets</td>
<td className="text-lg-right">{info.maxNumberOfAsset}</td>
</tr>
<tr>
<td>Number of Markets</td>
<td className="text-lg-right">{info.numberOfMarkets}</td>
</tr>
</InstructionCard>
);
}

View File

@ -0,0 +1,72 @@
import React from "react";
import { SignatureResult, TransactionInstruction } from "@solana/web3.js";
import { InstructionCard } from "../InstructionCard";
import { Address } from "components/common/Address";
import { Redeem } from "./types";
export function RedeemDetailsCard(props: {
ix: TransactionInstruction;
index: number;
result: SignatureResult;
info: Redeem;
innerCards?: JSX.Element[];
childIndex?: number;
}) {
const { ix, index, result, info, innerCards, childIndex } = props;
return (
<InstructionCard
ix={ix}
index={index}
result={result}
title="Bonfida Bot: Redeem"
innerCards={innerCards}
childIndex={childIndex}
>
<tr>
<td>Program</td>
<td className="text-lg-right">
<Address pubkey={info.programId} alignRight link />
</td>
</tr>
<tr>
<td>Bot Token Mint</td>
<td className="text-lg-right">
<Address pubkey={info.mintKey} alignRight link />
</td>
</tr>
<tr>
<td>Bot Address</td>
<td className="text-lg-right">
<Address pubkey={info.poolKey} alignRight link />
</td>
</tr>
<tr>
<td>Source Bot Token Owner</td>
<td className="text-lg-right">
<Address pubkey={info.sourcePoolTokenKey} alignRight link />
</td>
</tr>
<tr>
<td>Source Bot Token Address</td>
<td className="text-lg-right">
<Address pubkey={info.sourcePoolTokenKey} alignRight link />
</td>
</tr>
<tr>
<td>Pool Seed</td>
<td className="text-lg-right">{info.poolSeed}</td>
</tr>
<tr>
<td>Pool Token Amount</td>
<td className="text-lg-right">{info.poolTokenAmount}</td>
</tr>
</InstructionCard>
);
}

View File

@ -0,0 +1,108 @@
import React from "react";
import { SignatureResult, TransactionInstruction } from "@solana/web3.js";
import { InstructionCard } from "../InstructionCard";
import { Address } from "components/common/Address";
import { SettleFunds } from "./types";
export function SettleFundsDetailsCard(props: {
ix: TransactionInstruction;
index: number;
result: SignatureResult;
info: SettleFunds;
innerCards?: JSX.Element[];
childIndex?: number;
}) {
const { ix, index, result, info, innerCards, childIndex } = props;
return (
<InstructionCard
ix={ix}
index={index}
result={result}
title="Bonfida Bot: Settle Funds"
innerCards={innerCards}
childIndex={childIndex}
>
<tr>
<td>Program</td>
<td className="text-lg-right">
<Address pubkey={info.programId} alignRight link />
</td>
</tr>
<tr>
<td>Market</td>
<td className="text-lg-right">
<Address pubkey={info.market} alignRight link />
</td>
</tr>
<tr>
<td>Open Orders</td>
<td className="text-lg-right">
<Address pubkey={info.openOrdersKey} alignRight link />
</td>
</tr>
<tr>
<td>Bot Address</td>
<td className="text-lg-right">
<Address pubkey={info.poolKey} alignRight link />
</td>
</tr>
<tr>
<td>Bot Token Mint</td>
<td className="text-lg-right">
<Address pubkey={info.poolMintKey} alignRight link />
</td>
</tr>
<tr>
<td>Coin Vault</td>
<td className="text-lg-right">
<Address pubkey={info.coinVaultKey} alignRight link />
</td>
</tr>
<tr>
<td>Pc Vault</td>
<td className="text-lg-right">
<Address pubkey={info.pcVaultKey} alignRight link />
</td>
</tr>
<tr>
<td>Bot's Coin Address</td>
<td className="text-lg-right">
<Address pubkey={info.coinPoolAssetKey} alignRight link />
</td>
</tr>
<tr>
<td>Bot's Pc Address</td>
<td className="text-lg-right">
<Address pubkey={info.pcPoolAssetKey} alignRight link />
</td>
</tr>
<tr>
<td>Vault Signer</td>
<td className="text-lg-right">
<Address pubkey={info.vaultSignerKey} alignRight link />
</td>
</tr>
<tr>
<td>Serum Program ID</td>
<td className="text-lg-right">
<Address pubkey={info.dexProgramKey} alignRight link />
</td>
</tr>
<tr>
<td>Pool Seed</td>
<td className="text-lg-right">{info.poolSeed}</td>
</tr>
</InstructionCard>
);
}

View File

@ -0,0 +1,433 @@
/* eslint-disable @typescript-eslint/no-redeclare */
import { PublicKey, TransactionInstruction } from "@solana/web3.js";
import {
enums,
number,
type,
Infer,
create,
array,
string,
optional,
coerce,
any,
} from "superstruct";
import {
Instruction,
decodeInstruction,
BONFIDABOT_PROGRAM_ID,
} from "bonfida-bot";
export const SERUM_DECODED_MAX = 6;
export type Side = Infer<typeof Side>;
export const Side = enums([0, 1]);
export type OrderType = Infer<typeof OrderType>;
export const OrderType = enums([0, 1, 2]);
const PublicKeyToString = coerce(string(), any(), (value) => value.toBase58());
export type InitializeBot = {
systemProgramAccount: PublicKey;
rentSysvarAccount: PublicKey;
splTokenProgramAccount: PublicKey;
poolAccount: PublicKey;
mintAccount: PublicKey;
payerAccount: PublicKey;
poolSeed: string;
maxNumberOfAsset: number | undefined | null;
numberOfMarkets: number;
programId: PublicKey;
};
export const InitializeBotDecode = type({
poolSeed: string(),
maxNumberOfAsset: optional(number()),
numberOfMarkets: number(),
});
export const decodeInitializeBot = (
ix: TransactionInstruction
): InitializeBot => {
const decoded = create(
decodeInstruction(ix.data, Instruction.Init),
InitializeBotDecode
);
const initializeBot: InitializeBot = {
systemProgramAccount: ix.keys[0].pubkey,
rentSysvarAccount: ix.keys[1].pubkey,
splTokenProgramAccount: ix.keys[2].pubkey,
poolAccount: ix.keys[3].pubkey,
mintAccount: ix.keys[4].pubkey,
payerAccount: ix.keys[5].pubkey,
poolSeed: decoded.poolSeed,
maxNumberOfAsset: decoded.maxNumberOfAsset,
numberOfMarkets: decoded.numberOfMarkets,
programId: ix.programId,
};
return initializeBot;
};
export type CreateBot = {
splTokenProgramId: PublicKey;
clockSysvarKey: PublicKey;
mintKey: PublicKey;
poolKey: PublicKey;
poolSeed: string;
targetPoolTokenKey: PublicKey;
serumProgramId: PublicKey;
signalProviderKey: PublicKey;
depositAmounts: number[] | undefined | null;
markets: string[] | undefined | null;
feeCollectionPeriod: number;
feeRatio: number;
programId: PublicKey;
};
export const CreateBotDecode = type({
poolSeed: string(),
feeCollectionPeriod: number(),
feeRatio: number(),
depositAmounts: array(number()),
markets: array(PublicKeyToString),
});
export const decodeCreateBot = (ix: TransactionInstruction): CreateBot => {
const decoded = create(
decodeInstruction(ix.data, Instruction.Create),
CreateBotDecode
);
const createBot: CreateBot = {
splTokenProgramId: ix.keys[0].pubkey,
clockSysvarKey: ix.keys[1].pubkey,
mintKey: ix.keys[4].pubkey,
poolKey: ix.keys[6].pubkey,
poolSeed: decoded.poolSeed,
targetPoolTokenKey: ix.keys[5].pubkey,
serumProgramId: ix.keys[2].pubkey,
signalProviderKey: ix.keys[3].pubkey,
depositAmounts: decoded.depositAmounts,
markets: decoded.markets,
feeCollectionPeriod: decoded.feeCollectionPeriod,
feeRatio: decoded.feeRatio,
programId: ix.programId,
};
return createBot;
};
export type Deposit = {
splTokenProgramId: PublicKey;
programId: PublicKey;
sigProviderFeeReceiverKey: PublicKey;
bonfidaFeeReceiverKey: PublicKey;
bonfidaBuyAndBurnKey: PublicKey;
mintKey: PublicKey;
poolKey: PublicKey;
targetPoolTokenKey: PublicKey;
poolSeed: string;
poolTokenAmount: number;
};
export const DepositDecode = type({
poolSeed: string(),
poolTokenAmount: number(),
});
export const decodeDeposit = (ix: TransactionInstruction): Deposit => {
const decoded = create(
decodeInstruction(ix.data, Instruction.Deposit),
DepositDecode
);
const deposit: Deposit = {
splTokenProgramId: ix.keys[0].pubkey,
programId: ix.programId,
sigProviderFeeReceiverKey: ix.keys[3].pubkey,
bonfidaFeeReceiverKey: ix.keys[4].pubkey,
bonfidaBuyAndBurnKey: ix.keys[5].pubkey,
mintKey: ix.keys[1].pubkey,
poolKey: ix.keys[6].pubkey,
targetPoolTokenKey: ix.keys[2].pubkey,
poolSeed: decoded.poolSeed,
poolTokenAmount: decoded.poolTokenAmount,
};
return deposit;
};
export type CreateOrder = {
programId: PublicKey;
signalProviderKey: PublicKey;
market: PublicKey;
payerPoolAssetKey: PublicKey;
openOrdersKey: PublicKey;
serumRequestQueue: PublicKey;
serumEventQueue: PublicKey;
serumMarketBids: PublicKey;
serumMarketAsks: PublicKey;
poolKey: PublicKey;
coinVaultKey: PublicKey;
pcVaultKey: PublicKey;
splTokenProgramId: PublicKey;
dexProgramKey: PublicKey;
rentProgramId: PublicKey;
srmReferrerKey: PublicKey | null | undefined;
poolSeed: string;
side: Side;
limitPrice: number;
ratioOfPoolAssetsToTrade: number;
orderType: OrderType;
clientId: number;
coinLotSize: number;
pcLotSize: number;
targetMint: string;
};
export const CreateDecode = type({
poolSeed: string(),
side: Side,
limitPrice: number(),
ratioOfPoolAssetsToTrade: number(),
orderType: OrderType,
clientId: number(),
coinLotSize: number(),
pcLotSize: number(),
targetMint: string(),
});
export const decodeCreateOrder = (ix: TransactionInstruction): CreateOrder => {
const decoded = create(
decodeInstruction(ix.data, Instruction.CreateOrder),
CreateDecode
);
const createOrder: CreateOrder = {
programId: ix.programId,
signalProviderKey: ix.keys[0].pubkey,
market: ix.keys[1].pubkey,
payerPoolAssetKey: ix.keys[2].pubkey,
openOrdersKey: ix.keys[3].pubkey,
serumRequestQueue: ix.keys[5].pubkey,
serumEventQueue: ix.keys[4].pubkey,
serumMarketBids: ix.keys[6].pubkey,
serumMarketAsks: ix.keys[7].pubkey,
poolKey: ix.keys[8].pubkey,
coinVaultKey: ix.keys[9].pubkey,
pcVaultKey: ix.keys[10].pubkey,
splTokenProgramId: ix.keys[11].pubkey,
dexProgramKey: ix.keys[13].pubkey,
rentProgramId: ix.keys[12].pubkey,
srmReferrerKey: ix.keys[14]?.pubkey,
// Miss maxQuantity
//
poolSeed: decoded.poolSeed,
side: decoded.side,
limitPrice: decoded.limitPrice,
ratioOfPoolAssetsToTrade: decoded.ratioOfPoolAssetsToTrade,
orderType: decoded.orderType,
clientId: decoded.clientId,
coinLotSize: decoded.coinLotSize,
pcLotSize: decoded.pcLotSize,
targetMint: decoded.targetMint,
};
return createOrder;
};
export type CancelOrder = {
programId: PublicKey;
signalProviderKey: PublicKey;
market: PublicKey;
openOrdersKey: PublicKey;
serumEventQueue: PublicKey;
serumMarketBids: PublicKey;
serumMarketAsks: PublicKey;
poolKey: PublicKey;
dexProgramKey: PublicKey;
poolSeed: string;
side: Side;
orderId: number;
};
export const CancelOrderDecode = type({
poolSeed: string(),
side: Side,
orderId: number(),
});
export const decodeCancelOrder = (ix: TransactionInstruction): CancelOrder => {
const decoded = create(
decodeInstruction(ix.data, Instruction.CancelOrder),
CancelOrderDecode
);
const cancelOrder: CancelOrder = {
programId: ix.programId,
signalProviderKey: ix.keys[0].pubkey,
market: ix.keys[1].pubkey,
openOrdersKey: ix.keys[2].pubkey,
serumEventQueue: ix.keys[3].pubkey,
serumMarketBids: ix.keys[4].pubkey,
serumMarketAsks: ix.keys[5].pubkey,
poolKey: ix.keys[6].pubkey,
dexProgramKey: ix.keys[7].pubkey,
//
poolSeed: decoded.poolSeed,
side: decoded.side,
orderId: decoded.orderId,
};
return cancelOrder;
};
export type SettleFunds = {
programId: PublicKey;
market: PublicKey;
openOrdersKey: PublicKey;
poolKey: PublicKey;
poolMintKey: PublicKey;
coinVaultKey: PublicKey;
pcVaultKey: PublicKey;
coinPoolAssetKey: PublicKey;
pcPoolAssetKey: PublicKey;
vaultSignerKey: PublicKey;
splTokenProgramId: PublicKey;
dexProgramKey: PublicKey;
srmReferrerKey: PublicKey | null;
poolSeed: string;
};
export const SettleFundsDecode = type({
poolSeed: string(),
pcIndex: number(),
orderId: optional(number()),
});
export const decodeSettleFunds = (ix: TransactionInstruction): SettleFunds => {
const decoded = create(
decodeInstruction(ix.data, Instruction.SettleFunds),
SettleFundsDecode
);
const settleFunds: SettleFunds = {
programId: ix.programId,
market: ix.keys[0].pubkey,
openOrdersKey: ix.keys[1].pubkey,
poolKey: ix.keys[2].pubkey,
poolMintKey: ix.keys[3].pubkey,
coinVaultKey: ix.keys[4].pubkey,
pcVaultKey: ix.keys[5].pubkey,
coinPoolAssetKey: ix.keys[6].pubkey,
pcPoolAssetKey: ix.keys[7].pubkey,
vaultSignerKey: ix.keys[8].pubkey,
splTokenProgramId: ix.keys[9].pubkey,
dexProgramKey: ix.keys[10].pubkey,
srmReferrerKey: ix.keys[11]?.pubkey,
poolSeed: decoded.poolSeed,
};
return settleFunds;
};
export type Redeem = {
splTokenProgramId: PublicKey;
programId: PublicKey;
mintKey: PublicKey;
poolKey: PublicKey;
sourcePoolTokenOwnerKey: PublicKey;
sourcePoolTokenKey: PublicKey;
poolSeed: string;
poolTokenAmount: number;
};
export const RedeemDecode = type({
poolSeed: string(),
poolTokenAmount: number(),
});
export const decodeRedeem = (ix: TransactionInstruction): Redeem => {
const decoded = create(
decodeInstruction(ix.data, Instruction.Redeem),
RedeemDecode
);
const redeem: Redeem = {
programId: ix.programId,
splTokenProgramId: ix.keys[0].pubkey,
mintKey: ix.keys[2].pubkey,
poolKey: ix.keys[5].pubkey,
sourcePoolTokenOwnerKey: ix.keys[3].pubkey,
sourcePoolTokenKey: ix.keys[4].pubkey,
poolSeed: decoded.poolSeed,
poolTokenAmount: decoded.poolTokenAmount,
};
return redeem;
};
export type CollectFees = {
splTokenProgramId: PublicKey;
clockSysvarKey: PublicKey;
programId: PublicKey;
poolKey: PublicKey;
mintKey: PublicKey;
signalProviderPoolTokenKey: PublicKey;
bonfidaFeePoolTokenKey: PublicKey;
bonfidaBnBPTKey: PublicKey;
poolSeed: string;
};
export const CollectFeesDecode = type({
poolSeed: string(),
});
export const decodeCollectFees = (ix: TransactionInstruction): CollectFees => {
const decoded = create(
decodeInstruction(ix.data, Instruction.CollectFees),
CollectFeesDecode
);
const collectFees: CollectFees = {
programId: ix.programId,
splTokenProgramId: ix.keys[0].pubkey,
clockSysvarKey: ix.keys[1].pubkey,
poolKey: ix.keys[2].pubkey,
mintKey: ix.keys[3].pubkey,
signalProviderPoolTokenKey: ix.keys[4].pubkey,
bonfidaFeePoolTokenKey: ix.keys[5].pubkey,
bonfidaBnBPTKey: ix.keys[6].pubkey,
poolSeed: decoded.poolSeed,
};
return collectFees;
};
export const isBonfidaBotInstruction = (
instruction: TransactionInstruction
) => {
return instruction.programId.equals(BONFIDABOT_PROGRAM_ID);
};
export const INSTRUCTION_LOOKUP: { [key: number]: string } = {
0: "Initialize Bot",
1: "Create Bot",
2: "Deposit",
3: "Create Order",
4: "Cancel Order",
5: "Settle Funds",
6: "Redeem",
7: "Collect Fees",
};
export const parseBonfidaBotInstructionTitle = (
instruction: TransactionInstruction
): string => {
const code = instruction.data[0];
if (!(code in INSTRUCTION_LOOKUP)) {
throw new Error(`Unrecognized Bonfida Bot instruction code: ${code}`);
}
return INSTRUCTION_LOOKUP[code];
};

View File

@ -20,6 +20,7 @@ import { TokenLendingDetailsCard } from "components/instruction/TokenLendingDeta
import { TokenSwapDetailsCard } from "components/instruction/TokenSwapDetailsCard";
import { WormholeDetailsCard } from "components/instruction/WormholeDetailsCard";
import { UnknownDetailsCard } from "components/instruction/UnknownDetailsCard";
import { BonfidaBotDetailsCard } from "components/instruction/BonfidaBotDetails";
import {
SignatureProps,
INNER_INSTRUCTIONS_START_SLOT,
@ -28,6 +29,7 @@ import { intoTransactionInstruction } from "utils/tx";
import { isSerumInstruction } from "components/instruction/serum/types";
import { isTokenLendingInstruction } from "components/instruction/token-lending/types";
import { isTokenSwapInstruction } from "components/instruction/token-swap/types";
import { isBonfidaBotInstruction } from "components/instruction/bonfida-bot/types";
import { useFetchTransactionDetails } from "providers/transactions/details";
import {
useTransactionDetails,
@ -208,7 +210,9 @@ function renderInstructionCard({
childIndex,
};
if (isSerumInstruction(transactionIx)) {
if (isBonfidaBotInstruction(transactionIx)) {
return <BonfidaBotDetailsCard key={key} {...props} />;
} else if (isSerumInstruction(transactionIx)) {
return <SerumDetailsCard key={key} {...props} />;
} else if (isTokenSwapInstruction(transactionIx)) {
return <TokenSwapDetailsCard key={key} {...props} />;

View File

@ -24,6 +24,10 @@ import {
isSerumInstruction,
parseSerumInstructionTitle,
} from "components/instruction/serum/types";
import {
isBonfidaBotInstruction,
parseBonfidaBotInstructionTitle,
} from "components/instruction/bonfida-bot/types";
import { TOKEN_PROGRAM_ID } from "providers/accounts/tokens";
export type InstructionType = {
@ -105,6 +109,16 @@ export function getTokenInstructionName(
} else {
return undefined;
}
} else if (
transactionInstruction &&
isBonfidaBotInstruction(transactionInstruction)
) {
try {
name = parseBonfidaBotInstructionTitle(transactionInstruction);
} catch (error) {
reportError(error, { signature: signatureInfo.signature });
return undefined;
}
} else if (
transactionInstruction &&
isSerumInstruction(transactionInstruction)