Skip to content
8 changes: 4 additions & 4 deletions bun.lock
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
},
"packages/seismic-react": {
"name": "seismic-react",
"version": "1.0.50",
"version": "1.0.53",
"peerDependencies": {
"@rainbow-me/rainbowkit": "^2.0.0",
"react": "^18",
Expand All @@ -86,7 +86,7 @@
},
"packages/seismic-viem": {
"name": "seismic-viem",
"version": "1.0.50",
"version": "1.0.54",
"dependencies": {
"@noble/ciphers": "^1.2.0",
"@noble/curves": "^1.8.0",
Expand Down Expand Up @@ -2678,7 +2678,7 @@

"rpc-websockets/uuid": ["[email protected]", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="],

"seismic-bot/@types/bun": ["@types/[email protected].3", "", { "dependencies": { "bun-types": "1.3.3" } }, "sha512-ogrKbJ2X5N0kWLLFKeytG0eHDleBYtngtlbu9cyBKFtNL3cnpDZkNdQj8flVf6WTZUX5ulI9AY1oa7ljhSrp+g=="],
"seismic-bot/@types/bun": ["@types/[email protected].5", "", { "dependencies": { "bun-types": "1.3.5" } }, "sha512-RnygCqNrd3srIPEWBd5LFeUYG7plCoH2Yw9WaZGyNmdTEei+gWaHqydbaIRkIkcbXwhBT94q78QljxN0Sk838w=="],

"seismic-spammer/seismic-viem": ["[email protected]", "", { "dependencies": { "@noble/ciphers": "^1.2.0", "@noble/curves": "^1.8.0", "@noble/hashes": "^1.7.0", "viem": "^2.21.50" } }, "sha512-xw6lZuZ0l1SeoAFfaqpIY2Hd09WtsjqKWlqtDqWZ3ZNStOCYEFR6m8W7MQYnc1fKpSV93JJNsV9m0GOoclPYXQ=="],

Expand Down Expand Up @@ -2798,7 +2798,7 @@

"p-locate/p-limit/yocto-queue": ["[email protected]", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],

"seismic-bot/@types/bun/bun-types": ["[email protected].3", "", { "dependencies": { "@types/node": "*" } }, "sha512-z3Xwlg7j2l9JY27x5Qn3Wlyos8YAp0kKRlrePAOjgjMGS5IG6E7Jnlx736vH9UVI4wUICwwhC9anYL++XeOgTQ=="],
"seismic-bot/@types/bun/bun-types": ["[email protected].5", "", { "dependencies": { "@types/node": "*" } }, "sha512-inmAYe2PFLs0SUbFOWSVD24sg1jFlMPxOjOSSCYqUgn4Hsc3rDc7dFvfVYjFPNHtov6kgUeulV4SxbuIV/stPw=="],

"seismic-viem-tests/@types/bun/bun-types": ["[email protected]", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-04+Eha5NP7Z0A9YgDAzMk5PHR16ZuLVa83b26kH5+cp1qZW4F6FmAURngE7INf4tKOvCE69vYvDEwoNl1tGiWw=="],

Expand Down
2 changes: 1 addition & 1 deletion packages/seismic-viem/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "seismic-viem",
"version": "1.0.53",
"version": "1.0.54",
"description": "Typescript interface for Seismic",
"type": "module",
"main": "./dist/_cjs/index.js",
Expand Down
35 changes: 35 additions & 0 deletions packages/seismic-viem/src/abis/directory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import type { Abi, Address } from 'viem'

export const DIRECTORY_ADDRESS =
'0x1000000000000000000000000000000000000004' as Address

export const DirectoryAbi = [
{
inputs: [{ name: '_addr', type: 'address' }],
name: 'checkHasKey',
outputs: [{ type: 'bool' }],
stateMutability: 'view',
type: 'function',
},
{
inputs: [{ name: 'to', type: 'address' }],
name: 'keyHash',
outputs: [{ type: 'bytes32' }],
stateMutability: 'view',
type: 'function',
},
{
inputs: [],
name: 'getKey',
outputs: [{ type: 'uint256' }],
stateMutability: 'view',
type: 'function',
},
{
inputs: [{ name: '_key', type: 'suint256' }],
name: 'setKey',
outputs: [],
stateMutability: 'nonpayable',
type: 'function',
},
] as const satisfies Abi
185 changes: 185 additions & 0 deletions packages/seismic-viem/src/abis/src20.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
import type { Abi } from 'viem'

export const SRC20Abi = [
{
inputs: [
{
internalType: 'address',
name: 'owner',
type: 'address',
indexed: true,
},
{
internalType: 'address',
name: 'spender',
type: 'address',
indexed: true,
},
{
internalType: 'bytes32',
name: 'encryptKeyHash',
type: 'bytes32',
indexed: true,
},
{
internalType: 'bytes',
name: 'encryptedAmount',
type: 'bytes',
indexed: false,
},
],
type: 'event',
name: 'Approval',
anonymous: false,
},
{
inputs: [
{
internalType: 'address',
name: 'from',
type: 'address',
indexed: true,
},
{
internalType: 'address',
name: 'to',
type: 'address',
indexed: true,
},
{
internalType: 'bytes32',
name: 'encryptKeyHash',
type: 'bytes32',
indexed: true,
},
{
internalType: 'bytes',
name: 'encryptedAmount',
type: 'bytes',
indexed: false,
},
],
type: 'event',
name: 'Transfer',
anonymous: false,
},
{
inputs: [],
stateMutability: 'view',
type: 'function',
name: 'DOMAIN_SEPARATOR',
outputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }],
},
{
inputs: [],
stateMutability: 'view',
type: 'function',
name: 'INTELLIGENCE_ADDRESS',
outputs: [{ internalType: 'address', name: '', type: 'address' }],
},
{
inputs: [{ internalType: 'address', name: 'spender', type: 'address' }],
stateMutability: 'view',
type: 'function',
name: 'allowance',
outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],
},
{
inputs: [
{ internalType: 'address', name: 'spender', type: 'address' },
{ internalType: 'suint256', name: 'amount', type: 'suint256' },
],
stateMutability: 'nonpayable',
type: 'function',
name: 'approve',
outputs: [{ internalType: 'bool', name: '', type: 'bool' }],
},
{
inputs: [],
stateMutability: 'view',
type: 'function',
name: 'balance',
outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],
},
{
inputs: [],
stateMutability: 'view',
type: 'function',
name: 'decimals',
outputs: [{ internalType: 'uint8', name: '', type: 'uint8' }],
},
{
inputs: [],
stateMutability: 'view',
type: 'function',
name: 'intelligence',
outputs: [
{
internalType: 'contract IIntelligence',
name: '',
type: 'address',
},
],
},
{
inputs: [],
stateMutability: 'view',
type: 'function',
name: 'name',
outputs: [{ internalType: 'string', name: '', type: 'string' }],
},
{
inputs: [{ internalType: 'address', name: '', type: 'address' }],
stateMutability: 'view',
type: 'function',
name: 'nonces',
outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],
},
{
inputs: [
{ internalType: 'address', name: 'owner', type: 'address' },
{ internalType: 'address', name: 'spender', type: 'address' },
{ internalType: 'suint256', name: 'value', type: 'suint256' },
{
internalType: 'uint256',
name: 'deadline',
type: 'uint256',
},
{ internalType: 'uint8', name: 'v', type: 'uint8' },
{ internalType: 'bytes32', name: 'r', type: 'bytes32' },
{ internalType: 'bytes32', name: 's', type: 'bytes32' },
],
outputs: [],
stateMutability: 'nonpayable',
type: 'function',
name: 'permit',
},
{
inputs: [],
stateMutability: 'view',
type: 'function',
name: 'symbol',
outputs: [{ internalType: 'string', name: '', type: 'string' }],
},
{
inputs: [
{ internalType: 'address', name: 'to', type: 'address' },
{ internalType: 'suint256', name: 'amount', type: 'suint256' },
],
stateMutability: 'nonpayable',
type: 'function',
name: 'transfer',
outputs: [{ internalType: 'bool', name: '', type: 'bool' }],
},
{
inputs: [
{ internalType: 'address', name: 'from', type: 'address' },
{ internalType: 'address', name: 'to', type: 'address' },
{ internalType: 'suint256', name: 'amount', type: 'suint256' },
],
stateMutability: 'nonpayable',
type: 'function',
name: 'transferFrom',
outputs: [{ internalType: 'bool', name: '', type: 'bool' }],
},
] as const satisfies Abi
18 changes: 18 additions & 0 deletions packages/seismic-viem/src/actions/src20/crypto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { Hex } from 'viem'

export const NONCE_LENGTH = 24 // 12 bytes in hex string

export function parseEncryptedData(encryptedData: Hex): {
ciphertext: Hex
nonce: Hex
} {
// Handle empty/zero encrypted data
if (!encryptedData || encryptedData === '0x' || encryptedData.length <= 2) {
throw new Error('Empty encrypted data - recipient has no key')
}

const nonce = `0x${encryptedData.slice(-NONCE_LENGTH)}` as Hex
const ciphertext = encryptedData.slice(0, -NONCE_LENGTH) as Hex

return { ciphertext, nonce }
}
74 changes: 74 additions & 0 deletions packages/seismic-viem/src/actions/src20/directory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import type { Address, Hex } from 'viem'
import { keccak256 } from 'viem'

import { DIRECTORY_ADDRESS } from '@sviem/abis/directory.ts'
import { DirectoryAbi } from '@sviem/abis/directory.ts'
import type { ShieldedWalletClient } from '@sviem/client.ts'
import { signedReadContract } from '@sviem/contract/read.ts'
import { shieldedWriteContract } from '@sviem/contract/write.ts'

const TX_TIMEOUT_MS = 30_000

function withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {
const timeout = new Promise<never>((_, reject) =>
setTimeout(
() => reject(new Error(`Transaction timed out after ${ms}ms`)),
ms
)
)
return Promise.race([promise, timeout])
}

export async function checkRegistration(
client: ShieldedWalletClient,
address: Address
): Promise<boolean> {
const hasKey = await client.readContract({
address: DIRECTORY_ADDRESS,
abi: DirectoryAbi,
functionName: 'checkHasKey',
args: [address],
})
return hasKey as boolean
}

export async function getKeyHash(
client: ShieldedWalletClient,
address: Address
): Promise<Hex> {
const keyHash = await client.readContract({
address: DIRECTORY_ADDRESS,
abi: DirectoryAbi,
functionName: 'keyHash',
args: [address],
})
return keyHash as Hex
}

export async function getKey(client: ShieldedWalletClient): Promise<Hex> {
const key = await signedReadContract(client, {
address: DIRECTORY_ADDRESS,
abi: DirectoryAbi,
functionName: 'getKey',
})
return ('0x' + (key as bigint).toString(16).padStart(64, '0')) as Hex // TODO: shift to different function
}

export async function registerKey(
client: ShieldedWalletClient,
aesKey: Hex
): Promise<Hex> {
const txPromise = shieldedWriteContract(client, {
chain: client.chain,
address: DIRECTORY_ADDRESS,
abi: DirectoryAbi,
functionName: 'setKey',
args: [BigInt(aesKey)],
})

return withTimeout(txPromise, TX_TIMEOUT_MS)
}

export function computeKeyHash(aesKey: Hex): Hex {
return keccak256(aesKey) as Hex
}
Loading