Skip to content

Commit

Permalink
Invoke host fn tweaks (#23)
Browse files Browse the repository at this point in the history
* tweaks the response for invoke host fns to expose fn name and args

* triggering build

* triggering build take 2
  • Loading branch information
aristidesstaffieri authored Jan 22, 2024
1 parent 735ec8a commit db41d06
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 30 deletions.
36 changes: 36 additions & 0 deletions src/helper/soroban-rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
scValToNative,
xdr,
SorobanRpc,
StrKey,
} from "stellar-sdk";
import { NetworkNames } from "./validate";

Expand Down Expand Up @@ -139,8 +140,43 @@ const buildTransfer = (
return tx.build();
};

// https://github.com/stellar/soroban-examples/blob/main/token/src/contract.rs
enum SorobanTokenInterface {
transfer = "transfer",
mint = "mint",
}

const getOpArgs = (fnName: string, args: xdr.ScVal[]) => {
let amount: number;
let from;
let to;

switch (fnName) {
case SorobanTokenInterface.transfer:
from = StrKey.encodeEd25519PublicKey(
args[0].address().accountId().ed25519()
);
to = StrKey.encodeEd25519PublicKey(
args[1].address().accountId().ed25519()
);
amount = scValToNative(args[2]);
break;
case SorobanTokenInterface.mint:
to = StrKey.encodeEd25519PublicKey(
args[0].address().accountId().ed25519()
);
amount = scValToNative(args[1]).toString();
break;
default:
amount = 0;
}

return { from, to, amount };
};

export {
buildTransfer,
getOpArgs,
getServer,
getTokenBalance,
getTokenDecimals,
Expand Down
52 changes: 33 additions & 19 deletions src/service/mercury/helpers/transformers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { OperationResult } from "@urql/core";
import { Horizon, scValToNative, xdr } from "stellar-sdk";
import { Horizon, StrKey, scValToNative, xdr } from "stellar-sdk";
import BigNumber from "bignumber.js";
import {
BASE_RESERVE,
Expand All @@ -8,6 +8,7 @@ import {
getAssetType,
} from "../../../helper/horizon-rpc";
import { formatTokenAmount } from "../../../helper/format";
import { getOpArgs } from "../../../helper/soroban-rpc";

// Transformers take an API response, and transform it/augment it for frontend consumption

Expand Down Expand Up @@ -153,7 +154,9 @@ interface MercuryAccountHistory {
auth: string;
hostFunction: string;
sorobanMeta: string;
source: string;
accountBySource: {
publickey: string;
};
tx: string;
opId: string;
txInfoByTx: {
Expand Down Expand Up @@ -863,23 +866,34 @@ const transformAccountHistory = async (
): Promise<Partial<Horizon.ServerApi.OperationRecord>[]> => {
const invokeHostFnEdges =
rawResponse.data?.invokeHostFnByPublicKey.edges || [];
const invokeHostFn = invokeHostFnEdges.map(
(edge) =>
({
auth: edge.node.auth,
hostFunction: edge.node.hostFunction,
sorobanMeta: edge.node.sorobanMeta,
source: edge.node.source,
tx: edge.node.tx,
type: "invoke_host_function",
type_i: 24,
id: edge.node.opId,
transaction_attr: {
operation_count: edge.node.txInfoByTx.opCount,
fee_charged: edge.node.txInfoByTx.fee,
},
} as Partial<Horizon.ServerApi.InvokeHostFunctionOperationRecord>)
);
const invokeHostFn = invokeHostFnEdges.map((edge) => {
const hostFn = xdr.HostFunction.fromXDR(
Buffer.from(edge.node.hostFunction, "base64")
);
const invocation = hostFn.invokeContract();
const fnName = invocation.functionName().toString();
return {
auth: edge.node.auth,
created_at: new Date(
edge.node.txInfoByTx.ledgerByLedger.closeTime * 1000
).toISOString(),
sorobanMeta: edge.node.sorobanMeta,
source_account: edge.node.accountBySource.publickey,
tx: edge.node.tx,
type: "invoke_host_function",
type_i: 24,
id: edge.node.opId,
transaction_attr: {
contractId: StrKey.encodeContract(
invocation.contractAddress().contractId()
),
fnName,
args: getOpArgs(fnName, invocation.args()),
operation_count: edge.node.txInfoByTx.opCount,
fee_charged: edge.node.txInfoByTx.fee,
},
} as Partial<Horizon.ServerApi.InvokeHostFunctionOperationRecord>;
});

const createAccountEdges =
rawResponse.data?.createAccountByPublicKey.edges || [];
Expand Down
19 changes: 12 additions & 7 deletions src/service/mercury/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -432,11 +432,18 @@ export class MercuryClient {
} catch (error) {
this.logger.error(error);
const _error = JSON.stringify(error);
this.rpcErrorCounter
.labels({
rpc: "Horizon",
})
.inc();
if (error && typeof error === "object" && "message" in error) {
const err = JSON.parse(error.message as string);
// Not found errors are normal for unfunded accounts, dont alert
if (err.name !== "NotFoundError") {
this.rpcErrorCounter
.labels({
rpc: "Horizon",
})
.inc();
}
}

return {
data: null,
error: _error,
Expand All @@ -446,11 +453,9 @@ export class MercuryClient {

getAccountHistoryMercury = async (pubKey: string) => {
try {
const xdrPubKey = new Address(pubKey).toScVal().toXDR("base64");
const getData = async () => {
const data = await this.urqlClient.query(query.getAccountHistory, {
pubKey,
xdrPubKey,
});
const errorMessage = getGraphQlError(data.error);
if (errorMessage) {
Expand Down
18 changes: 14 additions & 4 deletions src/service/mercury/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,24 +58,34 @@ export const query = {
contractId
keyXdr
valueXdr
ledgerTimestamp
ledger
entryDurability
txInfoByTx {
fee
opCount
txHash
ledger
ledgerByLedger {
closeTime
sequence
}
}
}
}
`
)}
}
`,
getAccountHistory: `
query GetAccountHistory($pubKey: String!, $xdrPubKey: String!) {
query GetAccountHistory($pubKey: String!) {
invokeHostFnByPublicKey(publicKeyText: $pubKey) {
edges {
node {
auth
hostFunction
sorobanMeta
source
accountBySource {
publickey
}
tx
opId
txInfoByTx {
Expand Down

0 comments on commit db41d06

Please sign in to comment.