Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion modules/sdk-coin-tempo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@
"@bitgo/abstract-eth": "^24.19.4",
"@bitgo/sdk-core": "^36.25.0",
"@bitgo/secp256k1": "^1.8.0",
"@bitgo/statics": "^58.19.0"
"@bitgo/statics": "^58.19.0",
"viem": "^2.21.0"
},
"devDependencies": {
"@bitgo/sdk-api": "^1.72.2",
Expand Down
24 changes: 22 additions & 2 deletions modules/sdk-coin-tempo/src/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,25 @@
export const MAINNET_COIN = 'tempo';
export const TESTNET_COIN = 'ttempo';

export const VALID_ADDRESS_REGEX = /^[A-Za-z0-9]+$/; // Update with actual address format
export const VALID_PUBLIC_KEY_REGEX = /^[A-Fa-f0-9]{64}$/; // Update with actual public key format
export const VALID_ADDRESS_REGEX = /^0x[a-fA-F0-9]{40}$/;
export const VALID_PUBLIC_KEY_REGEX = /^[A-Fa-f0-9]{64}$/;

/**
* Tempo Chain IDs
*/
export const TEMPO_CHAIN_IDS = {
TESTNET: 42429, // Andantino testnet
// MAINNET: TBD
} as const;

/**
* TIP-20 Token Standard
* TIP-20 uses 6 decimals (unlike ERC-20's standard 18 decimals)
*/
export const TIP20_DECIMALS = 6;

/**
* AA Transaction Type
* Tempo uses EIP-7702 Account Abstraction with transaction type 0x76
*/
export const AA_TRANSACTION_TYPE = '0x76' as const;
3 changes: 3 additions & 0 deletions modules/sdk-coin-tempo/src/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ export * from './utils';
export * from './constants';
export * from './iface';
export * from './tip20Abi';
export * from './types';
export * from './transactionBuilder';
export * from './transaction';
74 changes: 51 additions & 23 deletions modules/sdk-coin-tempo/src/lib/tip20Abi.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,60 @@
/**
* TIP20 Token Standard ABI (Skeleton)
* TIP-20 Token Standard ABI
*
* TODO: Update this file when TIP20 ABI becomes available
* TIP-20 is Tempo's token standard, similar to ERC-20 but with:
* - 6 decimal places (instead of 18)
* - transferWithMemo function for attaching metadata
*/

/**
* Placeholder TIP20 ABI
* This is an empty array that should be replaced with the actual ABI
* TIP-20 transferWithMemo ABI
* Standard function for TIP-20 token transfers with memo field
*/
export const TIP20_ABI = [] as const;
export const TIP20_TRANSFER_WITH_MEMO_ABI = [
{
type: 'function',
name: 'transferWithMemo',
inputs: [
{ name: 'to', type: 'address' },
{ name: 'amount', type: 'uint256' },
{ name: 'memo', type: 'bytes32' },
],
outputs: [{ name: '', type: 'bool' }],
stateMutability: 'nonpayable',
},
] as const;

/**
* Placeholder for TIP20 Factory ABI
* Standard TIP-20 token ABI (similar to ERC-20)
*/
export const TIP20_FACTORY_ABI = [] as const;

/**
* Get the method signature for TIP20 transfer
* TODO: Update with actual method name if different from ERC20
*/
export function getTip20TransferSignature(): string {
return 'transfer(address,uint256)';
}

/**
* Get the method signature for TIP20 transferFrom
* TODO: Update with actual method name if different from ERC20
*/
export function getTip20TransferFromSignature(): string {
return 'transferFrom(address,address,uint256)';
}
export const TIP20_ABI = [
{
type: 'function',
name: 'balanceOf',
inputs: [{ name: 'account', type: 'address' }],
outputs: [{ name: '', type: 'uint256' }],
stateMutability: 'view',
},
{
type: 'function',
name: 'transfer',
inputs: [
{ name: 'to', type: 'address' },
{ name: 'amount', type: 'uint256' },
],
outputs: [{ name: '', type: 'bool' }],
stateMutability: 'nonpayable',
},
{
type: 'function',
name: 'transferFrom',
inputs: [
{ name: 'from', type: 'address' },
{ name: 'to', type: 'address' },
{ name: 'amount', type: 'uint256' },
],
outputs: [{ name: '', type: 'bool' }],
stateMutability: 'nonpayable',
},
...TIP20_TRANSFER_WITH_MEMO_ABI,
] as const;
91 changes: 91 additions & 0 deletions modules/sdk-coin-tempo/src/lib/transaction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/**
* TIP-20 Transaction
*
* Represents a Tempo Account Abstraction (AA) transaction (type 0x76)
* Supports single or batch TIP-20 token transfers with memos
*/

import { BaseTransaction, ParseTransactionError, TransactionType } from '@bitgo/sdk-core';
import { BaseCoin as CoinConfig } from '@bitgo/statics';
import type { Address, Hex } from 'viem';
import { Tip20Operation } from './types';

export class Tip20Transaction extends BaseTransaction {
private txRequest: any;
private _operations: Tip20Operation[];
private _signature?: { r: Hex; s: Hex; yParity: number };

constructor(_coinConfig: Readonly<CoinConfig>, request: any, operations: Tip20Operation[] = []) {
super(_coinConfig);
this.txRequest = request;
this._operations = operations;
}

get type(): TransactionType {
return TransactionType.Send;
}

canSign(): boolean {
return true;
}

async serialize(signature?: { r: Hex; s: Hex; yParity: number }): Promise<Hex> {
// TODO: Implement viem EIP-7702 transaction serialization
throw new ParseTransactionError('Transaction serialization not yet implemented');
}

getOperations(): Tip20Operation[] {
return [...this._operations];
}

getFeeToken(): Address | undefined {
return this.txRequest.feeToken;
}

getOperationCount(): number {
return this.txRequest.calls.length;
}

isBatch(): boolean {
return this.txRequest.calls.length > 1;
}

setSignature(signature: { r: Hex; s: Hex; yParity: number }): void {
this._signature = signature;
}

getSignature(): { r: Hex; s: Hex; yParity: number } | undefined {
return this._signature;
}

toJson(): Record<string, unknown> {
return {
type: this.txRequest.type,
chainId: this.txRequest.chainId,
nonce: this.txRequest.nonce,
maxFeePerGas: this.txRequest.maxFeePerGas.toString(),
maxPriorityFeePerGas: this.txRequest.maxPriorityFeePerGas.toString(),
gas: this.txRequest.gas.toString(),
callCount: this.txRequest.calls.length,
feeToken: this.txRequest.feeToken,
operations: this._operations,
signature: this._signature,
};
}

async toBroadcastFormat(): Promise<string> {
return await this.serialize(this._signature);
}

get id(): string {
return 'pending';
}

toString(): string {
return JSON.stringify(this.toJson(), null, 2);
}

canBroadcast(): boolean {
return this.txRequest.calls.length > 0 && this.txRequest.chainId > 0;
}
}
Loading
Loading