Skip to content

Commit

Permalink
Anchor instruction decoding
Browse files Browse the repository at this point in the history
  • Loading branch information
armaniferrante committed Jun 11, 2021
1 parent 83ba227 commit 6949302
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 14 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"@material-ui/core": "^4.11.4",
"@material-ui/icons": "^4.11.2",
"@material-ui/lab": "^4.0.0-alpha.58",
"@project-serum/anchor": "^0.7.0",
"@project-serum/anchor": "^0.8.0",
"@project-serum/serum": "^0.13.33",
"@project-serum/swap-ui": "^0.1.2",
"@solana/spl-token-registry": "^0.2.102",
Expand Down
99 changes: 92 additions & 7 deletions src/components/instructions/UnknownInstruction.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,58 @@
import React from 'react';
import React, { useState, useEffect } from 'react';
import LabelValue from './LabelValue';
import {
Table,
TableRow,
TableHead,
TableCell,
TableBody,
} from '@material-ui/core';
import Typography from '@material-ui/core/Typography';
import { Program, Provider } from '@project-serum/anchor';
import { useWallet } from '../../utils/wallet';
import { useConnection } from '../../utils/connection';

export default function UnknownInstruction({ instruction, onOpenAddress }) {
const [anchorProgram, setAnchorProgram] = useState(null);
const connection = useConnection();
const wallet = useWallet();

// Fetch the anchor IDL and generate a client. If the IDL isn't on chain,
// do nothing.
useEffect(() => {
const provider = new Provider(connection, wallet, {});
Program.at(instruction.programId, provider)
.then(setAnchorProgram)
.catch((err) => {});
}, [connection, wallet, instruction, setAnchorProgram]);

// Format all the fields of the instruction.
let formattedIx = null,
ix = null;
if (anchorProgram) {
ix = anchorProgram.coder.instruction.decode(instruction.rawData);
if (ix !== null) {
formattedIx = anchorProgram.coder.instruction.format(
ix,
instruction.accountMetas,
);
}
}

return (
<>
<Typography
variant="subtitle1"
style={{ fontWeight: 'bold' }}
gutterBottom
>
Unknown instruction:
{formattedIx && ix.name
? sentenceCase(ix.name)
: 'Unknown instruction:'}
</Typography>
<LabelValue
key="Program"
label="Program"
label={<b>Program</b>}
value={instruction.programId?.toBase58()}
link={true}
gutterBottom={true}
Expand All @@ -26,7 +64,13 @@ export default function UnknownInstruction({ instruction, onOpenAddress }) {
<>
<LabelValue
key={index + ''}
label={'Account #' + (index + 1)}
label={
<b>
{formattedIx && formattedIx.accounts[index].name
? sentenceCase(formattedIx.accounts[index].name)
: 'Account #' + (index + 1)}
</b>
}
value={accountMeta.publicKey.toBase58()}
link={true}
onClick={() => onOpenAddress(accountMeta.publicKey.toBase58())}
Expand All @@ -37,9 +81,50 @@ export default function UnknownInstruction({ instruction, onOpenAddress }) {
</>
);
})}
<Typography style={{ wordBreak: 'break-all' }}>
Data: {instruction.rawData}
</Typography>
{formattedIx ? (
<>
<Typography style={{ wordBreak: 'breaking-all' }}>
<b>Data:</b>
</Typography>
<DecodedInstruction formattedFields={formattedIx.args} />
</>
) : (
<Typography style={{ wordBreak: 'breaking-all' }}>
<b>Data:</b> {instruction.rawData}
</Typography>
)}
</>
);
}

function DecodedInstruction({ formattedFields }) {
return (
<Table>
<TableHead>
<TableRow>
<TableCell>#</TableCell>
<TableCell>Name</TableCell>
<TableCell>Type</TableCell>
<TableCell>Data</TableCell>
</TableRow>
</TableHead>
<TableBody>
{formattedFields.map((field, idx) => {
return (
<TableRow>
<TableCell>{idx.toString()}</TableCell>
<TableCell>{field.name}</TableCell>
<TableCell>{field.type}</TableCell>
<TableCell>{field.data}</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
);
}

function sentenceCase(field: string): string {
const result = field.replace(/([A-Z])/g, ' $1');
return result.charAt(0).toUpperCase() + result.slice(1);
}
47 changes: 41 additions & 6 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1892,13 +1892,13 @@
schema-utils "^2.6.5"
source-map "^0.7.3"

"@project-serum/anchor@^0.7.0":
version "0.7.0"
resolved "https://registry.yarnpkg.com/@project-serum/anchor/-/anchor-0.7.0.tgz#ef48b8233c0fbe6763699451eccfc5402503b012"
integrity sha512-SwY5OxJ6mYO3tTsYr3uQjlRX8tmb0P00u8T4ORWiYVz491fTcWIrGzqcrMHCvq9JFHMPvS6OR8BM0mfefx/DWw==
"@project-serum/anchor@^0.8.0":
version "0.8.0"
resolved "https://registry.yarnpkg.com/@project-serum/anchor/-/anchor-0.8.0.tgz#4172fa1c5f6680286a328d83d59f4f9139e058ee"
integrity sha512-fiwmtd2Q7ZbjapY8aZ9F3E1/0evB5HoOooBheFSkBYAFyQbh1T3YIf60hEdxHT6+YAEDhkkGLLMwrlAWGl28VA==
dependencies:
"@project-serum/borsh" "^0.2.2"
"@solana/web3.js" "^1.11.0"
"@solana/web3.js" "^1.17.0"
base64-js "^1.5.1"
bn.js "^5.1.2"
bs58 "^4.0.1"
Expand Down Expand Up @@ -2047,7 +2047,7 @@
tweetnacl "^1.0.0"
ws "^7.0.0"

"@solana/web3.js@^1.10.1", "@solana/web3.js@^1.11.0", "@solana/web3.js@^1.9.1":
"@solana/web3.js@^1.10.1", "@solana/web3.js@^1.9.1":
version "1.11.0"
resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.11.0.tgz#1cc9a25381687c82e444ad0633f028e050a06753"
integrity sha512-kmngWxntzp0HNhWInd7/3g2uqxdOrahvaHOyjilcRe+WCiC777gERz3+eIAbxIYx2zAZPjy02MZzLgoRHccZoQ==
Expand All @@ -2066,6 +2066,26 @@
superstruct "^0.14.2"
tweetnacl "^1.0.0"

"@solana/web3.js@^1.17.0":
version "1.18.0"
resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.18.0.tgz#f4c422a843aa57a1366d98b06cb6b45441644d59"
integrity sha512-ijAoRd4Sje1QYoPAwDr7KYlDK40FE7tAUa2V3wT4PGKatWf4ETDXoyYlW89J6vrqOT+mV3GUuaVC76tOFlrXyA==
dependencies:
"@babel/runtime" "^7.12.5"
bn.js "^5.0.0"
borsh "^0.4.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"

"@surma/rollup-plugin-off-main-thread@^1.1.1":
version "1.4.2"
resolved "https://registry.yarnpkg.com/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-1.4.2.tgz#e6786b6af5799f82f7ab3a82e53f6182d2b91a58"
Expand Down Expand Up @@ -3610,6 +3630,16 @@ boolbase@^1.0.0, boolbase@~1.0.0:
resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24=

borsh@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/borsh/-/borsh-0.4.0.tgz#9dd6defe741627f1315eac2a73df61421f6ddb9f"
integrity sha512-aX6qtLya3K0AkT66CmYWCCDr77qsE9arV05OmdFpmat9qu8Pg9J5tBUPDztAW5fNh/d/MyVG/OYziP52Ndzx1g==
dependencies:
"@types/bn.js" "^4.11.5"
bn.js "^5.0.0"
bs58 "^4.0.0"
text-encoding-utf-8 "^1.0.2"

brace-expansion@^1.1.7:
version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
Expand Down Expand Up @@ -12755,6 +12785,11 @@ test-exclude@^6.0.0:
glob "^7.1.4"
minimatch "^3.0.4"

text-encoding-utf-8@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz#585b62197b0ae437e3c7b5d0af27ac1021e10d13"
integrity sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==

[email protected], text-table@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
Expand Down

0 comments on commit 6949302

Please sign in to comment.