Skip to content

Commit

Permalink
handle v3 update calls
Browse files Browse the repository at this point in the history
  • Loading branch information
jorgenbuilder committed Oct 2, 2024
1 parent 1d770e5 commit 4bc3bed
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 1 deletion.
58 changes: 58 additions & 0 deletions src/services/capture/response.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
RequestStatusResponseStatus,
Certificate,
HttpAgent,
fromHex,
} from '@dfinity/agent';
import { decode as cborDecode } from 'cbor-x';
import { CandidDecodeResult, decodeCandidVals } from '../candid';
Expand Down Expand Up @@ -86,6 +87,63 @@ export async function decodeResponse(
);
}

// V3 update calls
// NOTE: I didn't implement the fallback to polling.
// This might mean that we will miss some responses.
// Reference: https://github.com/dfinity/agent-js/pull/906/files#diff-8e88073ceeb119a7b39f3e6616db4c23f5d3c0e923c194f1f0e5a1a6d54f5835R559
if ('status' in response && 'certificate' in response) {
const { message } = request as DecodedCallRequest;

const requestId = fromHex(request.requestId);

const details = messageDetails[message];

if (!details) {
console.log(messageDetails);
throw new Error(
`Unreachable: could not retrieve canister and method: ${message}`,
);
}

const { canisterId, method } = details;

const cert = new Certificate(response, new HttpAgent());
// manipulating the private `verified` property to bypass BLS verification. This is fine for debugging purposes, but it breaks the security model of the IC, so logs in the extension will not be trustable. There's a pure js BLS lib, but it will take 8 seconds to verify each certificate. There's a much faster WASM lib, but chrome extensions make that a pain (could be something worth implementing in the sandbox.)
(cert as any).verified = true;

const path = [new TextEncoder().encode('request_status'), requestId];
const status = new TextDecoder().decode(
cert.lookup([...path, 'status']),
);

switch (status) {
case RequestStatusResponseStatus.Replied: {
const buffer = cert.lookup([...path.flat(), 'reply']);
if (!buffer) {
throw new Error(
'Unreachable: successful read_state must have reply',
);
}
const reply = await decodeCandidVals(
canisterId,
method,
buffer,
);
return { status, reply, size } as RepliedReadStateResponse;
}

case RequestStatusResponseStatus.Rejected: {
const code = new Uint8Array(
cert.lookup([...path.flat(), 'reject_code'])!,
)[0];
const message = new TextDecoder().decode(
cert.lookup([...path.flat(), 'reject_message'])!,
);
return { status, message, code, size };
}
}
}

if ('status' in response) {
// Validate we have corresponding query request
if (request.requestType !== 'query') {
Expand Down
2 changes: 1 addition & 1 deletion src/services/capture/select.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const boundaryNodeRegex =
/https?:\/\/(?:.+)?((?:ic0\.app|dfinity.network|icp-api.io|icp0.io|mainnet.plugwallet.ooo)|localhost:[0-9]+)\/api\/v2\/canister\/(.+)\/(query|call|read_state)/;
/https?:\/\/(?:.+)?((?:ic0\.app|dfinity.network|icp-api.io|icp0.io|mainnet.plugwallet.ooo)|localhost:[0-9]+)\/api\/v(2|3)\/canister\/(.+)\/(query|call|read_state)/;

/**
* Determines whether a URL represents a request to an internet computer boundary node.
Expand Down

0 comments on commit 4bc3bed

Please sign in to comment.