Skip to content

Commit

Permalink
[Alpaca] Add block hash and timestamp (#8723)
Browse files Browse the repository at this point in the history
* [Alpaca] Add block hash and timestamp

* work on xrp coin module

* Add imp for stellar

* Some corrections of tests for xrp and get of ops

* handle of tezos coin

* add of changeset

* Corrections of reviews

* correction with Samy comments
  • Loading branch information
Salim-belkhir authored Dec 24, 2024
1 parent 3f98074 commit 2ae713b
Show file tree
Hide file tree
Showing 20 changed files with 174 additions and 58 deletions.
8 changes: 8 additions & 0 deletions .changeset/quick-frogs-develop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@ledgerhq/coin-stellar": minor
"@ledgerhq/coin-tezos": minor
"@ledgerhq/coin-xrp": minor
"@ledgerhq/coin-framework": minor
---

Add block informations to an operation (hash, time and height of a block)
6 changes: 3 additions & 3 deletions libs/coin-framework/src/api/types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export type BlockInfo = {
height: number;
hash: string;
time: Date;
hash?: string;
time?: Date;
};

export type Operation = {
Expand All @@ -10,7 +10,7 @@ export type Operation = {
type: string;
value: bigint;
fee: bigint;
blockHeight: number;
block: BlockInfo;
senders: string[];
recipients: string[];
date: Date;
Expand Down
10 changes: 8 additions & 2 deletions libs/coin-modules/coin-polkadot/src/logic/listOperations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ export type Operation = {
type: string;
value: bigint;
fee: bigint;
blockHeight: number;
block: {
height: number;
hash?: string;
time?: Date;
};
senders: string[];
recipients: string[];
date: Date;
Expand Down Expand Up @@ -43,7 +47,9 @@ const convertToCoreOperation = (address: string) => (operation: PolkadotOperatio
type,
value: BigInt(value.toString()),
fee: BigInt(fee.toString()),
blockHeight: blockHeight ?? 0,
block: {
height: blockHeight ?? 0,
},
senders,
recipients,
date,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export async function buildOptimisticOperation(
transactionSequenceNumber: transactionSequenceNumber?.plus(1).toNumber(),
extra: {
ledgerOpType: type,
blockTime: new Date(),
},
};

Expand Down
12 changes: 10 additions & 2 deletions libs/coin-modules/coin-stellar/src/logic/listOperations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ export type Operation = {
type: string;
value: bigint;
fee: bigint;
blockHeight: number;
block: {
hash?: string;
time?: Date;
height: number;
};
senders: string[];
recipients: string[];
date: Date;
Expand Down Expand Up @@ -41,7 +45,11 @@ const convertToCoreOperation = (address: string) => (operation: StellarOperation
type: operation.type,
value: BigInt(operation.value.toString()),
fee: BigInt(operation.fee.toString()),
blockHeight: operation.blockHeight!,
block: {
hash: operation.blockHash!,
time: operation.extra.blockTime,
height: operation.blockHeight!,
},
senders: operation.senders,
recipients: operation.recipients,
date: operation.date,
Expand Down
18 changes: 15 additions & 3 deletions libs/coin-modules/coin-stellar/src/network/horizon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ Horizon.AxiosClient.interceptors.request.use(config => {
return config;
});

// This function allows to fix the URL, because the url returned by the Stellar SDK is not the correct one.
// It replaces the host of the URL returned with the host of the explorer.
function useConfigHost(url: string): string {
const u = new URL(url);
u.host = new URL(coinConfig.getCoinConfig().explorer.url).host;
return u.toString();
}

Horizon.AxiosClient.interceptors.response.use(response => {
if (coinConfig.getCoinConfig().enableNetworkLogs) {
const { url, method } = response.config;
Expand All @@ -73,14 +81,18 @@ Horizon.AxiosClient.interceptors.response.use(response => {
// FIXME: workaround for the Stellar SDK not using the correct URL: the "next" URL
// included in server responses points to the node itself instead of our reverse proxy...
// (https://github.com/stellar/js-stellar-sdk/issues/637)

const next_href = response?.data?._links?.next?.href;

if (next_href) {
const next = new URL(next_href);
next.host = new URL(coinConfig.getCoinConfig().explorer.url).host;
response.data._links.next.href = next.toString();
response.data._links.next.href = useConfigHost(next_href);
}

response?.data?._embedded?.records?.forEach((r: any) => {
const href = r.transaction?._links?.ledger?.href;
if (href) r.transaction._links.ledger.href = useConfigHost(href);
});

return response;
});

Expand Down
4 changes: 3 additions & 1 deletion libs/coin-modules/coin-stellar/src/network/serialization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ async function formatOperation(
addr: string,
): Promise<StellarOperation> {
const transaction = await rawOperation.transaction();
const { hash: blockHash, closed_at: blockTime } = await transaction.ledger();
const type = getOperationType(rawOperation, addr);
const value = getValue(rawOperation, transaction, type);
const recipients = getRecipients(rawOperation);
Expand All @@ -103,9 +104,10 @@ async function formatOperation(
recipients,
transactionSequenceNumber: Number(transaction.source_account_sequence),
hasFailed: !rawOperation.transaction_successful,
blockHash: null,
blockHash: blockHash,
extra: {
ledgerOpType: type,
blockTime: new Date(blockTime),
},
};

Expand Down
1 change: 1 addition & 0 deletions libs/coin-modules/coin-stellar/src/types/bridge.fixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export function createFixtureOperation(operation?: Partial<StellarOperation>): S
let extra: StellarOperationExtra = {
assetAmount: operation?.extra?.assetAmount || undefined,
ledgerOpType: operation?.extra?.ledgerOpType || "IN",
blockTime: operation?.extra?.blockTime || faker.date.past(),
};
if (operation?.extra?.pagingToken) {
extra = {
Expand Down
1 change: 1 addition & 0 deletions libs/coin-modules/coin-stellar/src/types/bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ export type StellarOperationExtra = {
assetAmount?: string | undefined;
ledgerOpType: OperationType;
memo?: string;
blockTime: Date;
};

export type StellarAccount = Account;
1 change: 1 addition & 0 deletions libs/coin-modules/coin-tezos/src/api/index.integ.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ describe("Tezos Api", () => {
const isSenderOrReceipt =
operation.senders.includes(address) || operation.recipients.includes(address);
expect(isSenderOrReceipt).toBeTruthy();
expect(operation.block).toBeDefined();
});
});

Expand Down
12 changes: 10 additions & 2 deletions libs/coin-modules/coin-tezos/src/logic/listOperations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ export type Operation = {
type: string;
value: bigint;
fee: bigint;
blockHeight: number;
block: {
hash?: string;
height: number;
time?: Date;
};
senders: string[];
recipients: string[];
date: Date;
Expand Down Expand Up @@ -48,7 +52,11 @@ function convertOperation(
value: BigInt(amount),
// storageFee for transaction is always present
fee: BigInt(storageFee ?? 0),
blockHeight: 0, // operation.block is a string
block: {
hash: operation.block,
height: operation.level,
time: new Date(operation.timestamp),
},
senders: [sender?.address ?? ""],
recipients: [targetAddress],
date: new Date(timestamp),
Expand Down
42 changes: 30 additions & 12 deletions libs/coin-modules/coin-xrp/src/api/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,25 +41,29 @@ describe("listOperations", () => {
const fee = 10;
mockGetTransactions.mockResolvedValue([
{
ledger_hash: "HASH_VALUE_BLOCK",
hash: "HASH_VALUE",
close_time_iso: "2000-01-01T00:00:01Z",
meta: { delivered_amount: deliveredAmount.toString() },
tx: {
tx_json: {
TransactionType: "Payment",
Fee: fee.toString(),
hash: "HASH_VALUE",
inLedger: 1,
ledger_index: 1,
date: 1000,
Account: opSender,
Destination: opDestination,
Sequence: 1,
},
},
{
ledger_hash: "HASH_VALUE_BLOCK",
hash: "HASH_VALUE",
close_time_iso: "2000-01-01T00:00:01Z",
meta: { delivered_amount: deliveredAmount.toString() },
tx: {
tx_json: {
TransactionType: "Payment",
Fee: fee.toString(),
hash: "HASH_VALUE",
inLedger: 1,
ledger_index: 1,
date: 1000,
Account: opSender,
Destination: opDestination,
Expand All @@ -68,12 +72,14 @@ describe("listOperations", () => {
},
},
{
ledger_hash: "HASH_VALUE_BLOCK",
hash: "HASH_VALUE",
close_time_iso: "2000-01-01T00:00:01Z",
meta: { delivered_amount: deliveredAmount.toString() },
tx: {
tx_json: {
TransactionType: "Payment",
Fee: fee.toString(),
hash: "HASH_VALUE",
inLedger: 1,
ledger_index: 1,
date: 1000,
Account: opSender,
Destination: opDestination,
Expand Down Expand Up @@ -106,7 +112,11 @@ describe("listOperations", () => {
type: "Payment",
value: expectedValue,
fee: BigInt(10),
blockHeight: 1,
block: {
hash: "HASH_VALUE_BLOCK",
height: 1,
time: new Date("2000-01-01T00:00:01Z"),
},
senders: [opSender],
recipients: [opDestination],
date: new Date(1000000 + RIPPLE_EPOCH * 1000),
Expand All @@ -118,7 +128,11 @@ describe("listOperations", () => {
type: "Payment",
value: expectedValue,
fee: BigInt(10),
blockHeight: 1,
block: {
hash: "HASH_VALUE_BLOCK",
height: 1,
time: new Date("2000-01-01T00:00:01Z"),
},
senders: [opSender],
recipients: [opDestination],
date: new Date(1000000 + RIPPLE_EPOCH * 1000),
Expand All @@ -133,7 +147,11 @@ describe("listOperations", () => {
type: "Payment",
value: expectedValue,
fee: BigInt(10),
blockHeight: 1,
block: {
hash: "HASH_VALUE_BLOCK",
height: 1,
time: new Date("2000-01-01T00:00:01Z"),
},
senders: [opSender],
recipients: [opDestination],
date: new Date(1000000 + RIPPLE_EPOCH * 1000),
Expand Down
13 changes: 10 additions & 3 deletions libs/coin-modules/coin-xrp/src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,18 @@ async function operations(
address: string,
{ limit, start }: Pagination,
): Promise<[Operation[], number]> {
const [ops, index] = await listOperations(address, { limit, mostRecentIndex: start });
const [ops, index] = await listOperations(address, { limit, startAt: start ?? 0 });
return [
ops.map(op => {
const { simpleType, ...rest } = op;
return { ...rest } satisfies Operation;
const { simpleType, blockHash, blockTime, blockHeight, ...rest } = op;
return {
...rest,
block: {
height: blockHeight,
hash: blockHash,
time: blockTime,
},
} satisfies Operation;
}),
index,
];
Expand Down
9 changes: 5 additions & 4 deletions libs/coin-modules/coin-xrp/src/bridge/synchronization.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,13 @@ describe("getAccountShape", () => {
});
mockGetTransactions.mockResolvedValue([
{
ledger_hash: "HASH_VALUE_BLOCK",
hash: "HASH_VALUE",
meta: { delivered_amount: "100" },
tx: {
tx_json: {
TransactionType: "Payment",
Fee: "10",
hash: "HASH_VALUE",
inLedger: 1,
ledger_index: 1,
date: 1000,
Account: "account_addr",
Destination: "destination_addr",
Expand Down Expand Up @@ -117,7 +118,7 @@ describe("getAccountShape", () => {
operations: [
{
accountId: "js:2:ripple:address:",
blockHash: null,
blockHash: "HASH_VALUE_BLOCK",
blockHeight: 1,
date: new Date("2000-01-01T00:16:40.000Z"),
hash: "HASH_VALUE",
Expand Down
2 changes: 1 addition & 1 deletion libs/coin-modules/coin-xrp/src/bridge/synchronization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ async function filterOperations(
type: op.simpleType,
value: new BigNumber(op.value.toString()),
fee: new BigNumber(op.fee.toString()),
blockHash: null,
blockHash: op.blockHash,
blockHeight: op.blockHeight,
senders: op.senders,
recipients: op.recipients,
Expand Down
Loading

0 comments on commit 2ae713b

Please sign in to comment.