Skip to content

Commit

Permalink
add a test for rpc method as default for soroban xdr
Browse files Browse the repository at this point in the history
  • Loading branch information
Jeesun Kim authored and Jeesun Kim committed Jan 18, 2025
1 parent 4d63156 commit f6681b9
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 2 deletions.
55 changes: 53 additions & 2 deletions src/app/(sidebar)/transaction/submit/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,47 @@ const SUBMIT_OPTIONS = [
},
];

// Define operation types for better type safety
interface DecodedOperationBody {
extend_footprint_ttl?: { ext: string };
restore_footprint?: { ext: string };
invoke_host_function?: { ext: string };
}

interface DecodedOperation {
body: DecodedOperationBody;
}

// Move function outside component to prevent recreation
const isSorobanXdr = (jsonString: string): boolean => {
try {
const parsedXdr = JSON.parse(jsonString);
const operations = parsedXdr?.tx?.tx?.operations;

if (!Array.isArray(operations)) {
return false;
}

return operations.some((op: DecodedOperation) => {
const body = op?.body;
if (!body) {
return false;
}

const sorobanOps = [
body.extend_footprint_ttl,
body.restore_footprint,
body.invoke_host_function,
];

return sorobanOps.some((op) => op?.ext === "v0");
});
} catch (e) {
console.debug("Error parsing XDR:", e);
return false;
}
};

export default function SubmitTransaction() {
const { network, xdr, transaction } = useStore();
const { blob, updateXdrBlob } = xdr;
Expand All @@ -80,6 +121,7 @@ export default function SubmitTransaction() {
const [isSaveTxnModalVisible, setIsSaveTxnModalVisible] = useState(false);
const [isDropdownActive, setIsDropdownActive] = useState(false);
const [isDropdownVisible, setIsDropdownVisible] = useState(false);
const [isSorobanTx, setIsSorobanTx] = useState(false);
const [submitMethod, setSubmitMethod] = useState<"horizon" | "rpc" | string>(
"",
);
Expand Down Expand Up @@ -129,7 +171,9 @@ export default function SubmitTransaction() {
useEffect(() => {
const localStorageMethod = localStorageSettings.get(SETTINGS_SUBMIT_METHOD);

if (localStorageMethod) {
if (isSorobanTx && isRpcAvailable) {
setSubmitMethod("rpc");
} else if (localStorageMethod) {
setSubmitMethod(localStorageMethod);
} else {
setSubmitMethod(isRpcAvailable ? "rpc" : "horizon");
Expand All @@ -138,7 +182,7 @@ export default function SubmitTransaction() {
resetSubmitState();
// Not including resetSubmitState
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isRpcAvailable]);
}, [isRpcAvailable, isSorobanTx]);

// Scroll to response
useScrollIntoView(isSuccess, responseSuccessEl);
Expand Down Expand Up @@ -497,6 +541,13 @@ export default function SubmitTransaction() {
return null;
};

useEffect(() => {
if (xdrJson?.jsonString) {
const hasSorobanOp = isSorobanXdr(xdrJson.jsonString);
setIsSorobanTx(hasSorobanOp);
}
}, [xdrJson?.jsonString]);

return (
<Box gap="md" data-testid="submit-tx-xdr">
<PageCard heading="Submit Transaction">
Expand Down
25 changes: 25 additions & 0 deletions tests/submitTransactionPage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,25 @@ test.describe("Submit Transaction Page", () => {
// Omitting the API end result because the test gives inconsistenet results
});
});

test.describe("Update default submit method to RPC when it is a Soroban XDR", () => {
test("Submit Soroban", async ({ page }) => {
const xdrInput = page.getByLabel(
"Input a base-64 encoded TransactionEnvelope",
);
const submitMethodsBtn = page
.locator(".SubmitTx__buttons")
.getByRole("button", { name: /via/i });

await expect(submitMethodsBtn).toBeVisible();

// Input the Soroban XDR
await xdrInput.fill(MOCK_VALID_SOROBAN_TX_XDR.XDR);

// Check if the submit method button shows RPC as default
await expect(submitMethodsBtn).toHaveText("via RPC");
});
});
});

const testSuccessHashAndJson = async ({
Expand Down Expand Up @@ -538,6 +557,12 @@ const MOCK_VALID_SUCCESS_TX_XDR_RPC = {
hash: "00cb774dce521a93438236d49f8154ede32729a595c797d51c1a72c364056fd0",
};

const MOCK_VALID_SOROBAN_TX_XDR = {
XDR: "AAAAAgAAAAB+TL0HLiAjanMRnyeqyhb8Iu+4d1g2dl1cwPi1UZAigwAAtwUABiLjAAAAGQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAGQAAAAAAAHUwAAAAAQAAAAAAAAABAAAABgAAAAEg/u86MzPrVcpNrsFUa84T82Kss8DLAE9ZMxLqhM22HwAAABAAAAABAAAAAgAAAA8AAAAHQ291bnRlcgAAAAASAAAAAAAAAAB+TL0HLiAjanMRnyeqyhb8Iu+4d1g2dl1cwPi1UZAigwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtqEAAAABUZAigwAAAEADYbntiznotYPblvJQ35DiGEpMTQU9jCYANxV18VVGV6zDFSjB+qK++dF656Pr4oMTpyBVvE15YSo6ITxR5DoE",
JSON: `{"tx":{"tx":{"source_account":"GB7EZPIHFYQCG2TTCGPSPKWKC36CF35YO5MDM5S5LTAPRNKRSARIHWGG","fee":46853,"seq_num":1727208213184537,"cond":{"time":{"min_time":0,"max_time":0}},"memo":"none","operations":[{"source_account":null,"body":{"extend_footprint_ttl":{"ext":"v0","extend_to":30000}}}],"ext":{"v1":{"ext":"v0","resources":{"footprint":{"read_only":[{"contract_data":{"contract":"CAQP53Z2GMZ6WVOKJWXMCVDLZYJ7GYVMWPAMWACPLEZRF2UEZW3B636S","key":{"vec":[{"symbol":"Counter"},{"address":"GB7EZPIHFYQCG2TTCGPSPKWKC36CF35YO5MDM5S5LTAPRNKRSARIHWGG"}]},"durability":"persistent"}}],"read_write":[]},"instructions":0,"read_bytes":0,"write_bytes":0},"resource_fee":46753}}},"signatures":[{"hint":"51902283","signature":"0361b9ed8b39e8b583db96f250df90e2184a4c4d053d8c2600371575f1554657acc31528c1faa2bef9d17ae7a3ebe28313a72055bc4d79612a3a213c51e43a04"}]}}`,
hash: "0571508f487a343006d231d11f201a855f67973e0e019da6164b32b992dab46f",
};

const MOCK_VALID_TX_SUCCESS_HORIZON_RESPONSE = {
_links: {
self: {
Expand Down

0 comments on commit f6681b9

Please sign in to comment.