Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: refactor RPC starkNet_getTransactions with StarkScan #463

Merged
7 changes: 5 additions & 2 deletions packages/starknet-snap/src/__tests__/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import type {
} from '../chain/data-client/starkscan.type';
import { FeeToken } from '../types/snapApi';
import {
ContractFuncName,
TransactionDataVersion,
type AccContract,
type Transaction,
Expand Down Expand Up @@ -268,7 +269,7 @@ export function generateTransactions({
const txnType = getRandomData(_txnTypes);
const contractFuncName =
txnType == TransactionType.INVOKE
? getRandomData(['transfer', 'upgrade'])
? getRandomData(Object.values(ContractFuncName))
: '';

transactions.push(
Expand Down Expand Up @@ -303,6 +304,8 @@ function getTransactionTemplate() {
finalityStatus: '',
accountCalls: null,
version: 1,
maxFee: null,
actualFee: null,
dataVersion: TransactionDataVersion.V2,
};
}
Expand Down Expand Up @@ -464,7 +467,7 @@ export function generateTransactionRequests({
to: address,
amount: '1',
}),
entrypoint: 'transfer',
entrypoint: ContractFuncName.Transfer,
},
],
includeDeploy: false,
Expand Down
132 changes: 46 additions & 86 deletions packages/starknet-snap/src/chain/data-client/starkscan.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,18 @@
import { TransactionType, constants } from 'starknet';
import type { Struct } from 'superstruct';

import {
ContractFuncName,
TransactionDataVersion,
type Network,
type Transaction,
type TranscationAccountCall,
} from '../../types/snapState';
import {
TRANSFER_SELECTOR_HEX,
UPGRADE_SELECTOR_HEX,
} from '../../utils/constants';
import type { V2Transaction } from '../../types/snapState';
import { type Network, type Transaction } from '../../types/snapState';
import { InvalidNetworkError } from '../../utils/exceptions';
import {
newDeployTransaction,
newInvokeTransaction,
} from '../../utils/transaction';
import type { HttpHeaders } from '../api-client';
import { ApiClient, HttpMethod } from '../api-client';
import type { IDataClient } from '../data-client';
import type { StarkScanTransactionsResponse } from './starkscan.type';
import {
type StarkScanAccountCall,
type StarkScanTransaction,
type StarkScanOptions,
StarkScanTransactionsResponseStruct,
Expand Down Expand Up @@ -185,10 +179,6 @@ export class StarkScanClient extends ApiClient implements IDataClient {
return tx.transaction_type === TransactionType.DEPLOY_ACCOUNT;
}

protected isFundTransferTransaction(entrypoint: string): boolean {
return entrypoint === TRANSFER_SELECTOR_HEX;
}

protected getContractAddress(tx: StarkScanTransaction): string {
// backfill the contract address if it is null
return tx.contract_address ?? '';
Expand All @@ -207,94 +197,64 @@ export class StarkScanClient extends ApiClient implements IDataClient {
}

protected toTransaction(tx: StarkScanTransaction): Transaction {
/* eslint-disable @typescript-eslint/naming-convention */
/* eslint-disable @typescript-eslint/naming-convention, camelcase */
const {
transaction_hash: txnHash,
transaction_type: txnType,
timestamp,
transaction_finality_status: finalityStatus,
transaction_execution_status: executionStatus,
max_fee: maxFee,
max_fee,
actual_fee: actualFee,
revert_error: failureReason,
revert_error,
// account_calls representing the calls to invoke from the account contract, it can be multiple
// If the transaction is a deploy transaction, the account_calls is a empty array
account_calls: calls,
version,
version: txnVersion,
} = tx;

// account_calls representing the calls to invoke from the account contract, it can be multiple
// If the transaction is a deploy transaction, the account_calls is a empty array
const accountCalls = this.toAccountCall(calls);
const { chainId } = this.network;
const senderAddress = this.getSenderAddress(tx);
const failureReason = revert_error ?? '';
const maxFee = max_fee ?? '0';

let transaction: V2Transaction;

// eslint-disable-next-line no-negated-condition
if (!this.isDeployTransaction(tx)) {
transaction = newInvokeTransaction({
txnHash,
senderAddress,
chainId,
maxFee,
calls: calls.map((call) => ({
contractAddress: call.contract_address,
entrypoint: call.selector,
calldata: call.calldata,
})),
txnVersion,
});
} else {
transaction = newDeployTransaction({
txnHash,
senderAddress,
chainId,
txnVersion,
});
}

return {
txnHash,
txnType,
chainId: this.network.chainId,
senderAddress: this.getSenderAddress(tx),
...transaction,
// Override the fields from the StarkScanTransaction
timestamp,
finalityStatus,
executionStatus,
maxFee,
actualFee,
maxFee,
contractAddress: this.getContractAddress(tx),
accountCalls,
failureReason: failureReason ?? '',
version,
dataVersion: TransactionDataVersion.V2,
failureReason,
txnType,
};

/* eslint-enable */
}

protected toAccountCall(
accountCalls: StarkScanAccountCall[],
): Record<string, TranscationAccountCall[]> | null {
if (!accountCalls || accountCalls.length === 0) {
return null;
}

return accountCalls.reduce(
(
data: Record<string, TranscationAccountCall[]>,
accountCallArg: StarkScanAccountCall,
) => {
const {
contract_address: contract,
selector,
calldata: contractCallData,
} = accountCallArg;

const contractFuncName = this.selectorHexToName(selector);
if (!Object.prototype.hasOwnProperty.call(data, contract)) {
data[contract] = [];
}

const accountCall: TranscationAccountCall = {
contract,
contractFuncName,
contractCallData,
};

if (this.isFundTransferTransaction(selector)) {
accountCall.recipient = accountCallArg.calldata[0];
accountCall.amount = accountCallArg.calldata[1];
}

data[contract].push(accountCall);

return data;
},
{},
);
}

protected selectorHexToName(selector: string): string {
switch (selector.toLowerCase()) {
case TRANSFER_SELECTOR_HEX.toLowerCase():
return ContractFuncName.Transfer;
case UPGRADE_SELECTOR_HEX.toLowerCase():
return ContractFuncName.Upgrade;
default:
return selector;
}
}
}
Loading
Loading