ox
Version:
Ethereum Standard Library
199 lines (179 loc) • 5.7 kB
text/typescript
import { AbiEvent, AbiParameters } from 'ox'
import { ReceivePolicyReceipt } from 'ox/tempo'
import { describe, expect, test } from 'vite-plus/test'
const token = '0x20c0000000000000000000000000000000000001'
const originator = '0x0000000000000000000000000000000000000aaa'
const recipient = '0x0000000000000000000000000000000000000bbb'
const zeroAddress = '0x0000000000000000000000000000000000000000'
const zeroHash =
'0x0000000000000000000000000000000000000000000000000000000000000000'
const witnessParameters = [
{
type: 'tuple',
components: [
{ name: 'version', type: 'uint8' },
{ name: 'token', type: 'address' },
{ name: 'recoveryAuthority', type: 'address' },
{ name: 'originator', type: 'address' },
{ name: 'recipient', type: 'address' },
{ name: 'blockedAt', type: 'uint64' },
{ name: 'blockedNonce', type: 'uint64' },
{ name: 'blockedReason', type: 'uint8' },
{ name: 'kind', type: 'uint8' },
{ name: 'memo', type: 'bytes32' },
],
},
] as const
function encodeWitness(
overrides: Partial<{
blockedReason: number
kind: number
}> = {},
) {
return AbiParameters.encode(witnessParameters, [
{
version: 1,
token,
recoveryAuthority: zeroAddress,
originator,
recipient,
blockedAt: 1234n,
blockedNonce: 5n,
blockedReason: overrides.blockedReason ?? 2,
kind: overrides.kind ?? 0,
memo: zeroHash,
},
])
}
const transferBlocked = AbiEvent.from(
'event TransferBlocked(address indexed token, address indexed receiver, uint64 indexed blockedNonce, uint256 amount, uint8 receiptVersion, bytes receipt)',
)
function blockedLog(witness: `0x${string}`) {
const { topics } = AbiEvent.encode(transferBlocked, {
token,
receiver: recipient,
blockedNonce: 5n,
})
const data = AbiParameters.encode(
[{ type: 'uint256' }, { type: 'uint8' }, { type: 'bytes' }],
[10_000_000n, 1, witness],
)
return { data, topics: topics as readonly `0x${string}`[] }
}
describe('decode', () => {
test('default', () => {
expect(ReceivePolicyReceipt.decode(encodeWitness())).toMatchInlineSnapshot(`
{
"blockedAt": 1234n,
"blockedNonce": 5n,
"blockedReason": "receivePolicy",
"kind": "transfer",
"memo": "0x0000000000000000000000000000000000000000000000000000000000000000",
"originator": "0x0000000000000000000000000000000000000aaa",
"recipient": "0x0000000000000000000000000000000000000bBB",
"recoveryAuthority": "0x0000000000000000000000000000000000000000",
"token": "0x20C0000000000000000000000000000000000001",
"version": 1,
}
`)
})
test('behavior: kind mint', () => {
expect(ReceivePolicyReceipt.decode(encodeWitness({ kind: 1 })).kind).toBe(
'mint',
)
})
test('behavior: blocked reason token filter', () => {
expect(
ReceivePolicyReceipt.decode(encodeWitness({ blockedReason: 1 }))
.blockedReason,
).toBe('tokenFilter')
})
})
describe('encode', () => {
test('round-trips with decode', () => {
const witness = encodeWitness()
expect(
ReceivePolicyReceipt.encode(ReceivePolicyReceipt.decode(witness)),
).toBe(witness)
})
test('behavior: maps enum strings back to indices', () => {
const receipt = ReceivePolicyReceipt.decode(
encodeWitness({ blockedReason: 1, kind: 1 }),
)
const reencoded = ReceivePolicyReceipt.encode(receipt)
expect(ReceivePolicyReceipt.decode(reencoded)).toEqual(receipt)
})
})
describe('fromLog', () => {
test('default', () => {
const witness = encodeWitness()
expect(ReceivePolicyReceipt.fromLog(blockedLog(witness))).toBe(witness)
})
test('error: non-matching log', () => {
expect(() =>
ReceivePolicyReceipt.fromLog({ data: '0x', topics: [zeroHash] }),
).toThrow()
})
})
describe('from', () => {
test('passthrough encoded receipt', () => {
const witness = encodeWitness()
expect(ReceivePolicyReceipt.from(witness)).toBe(witness)
})
test('from decoded fields', () => {
const witness = encodeWitness()
expect(
ReceivePolicyReceipt.from(ReceivePolicyReceipt.decode(witness)),
).toBe(witness)
})
})
describe('fromTransactionReceipt', () => {
test('single blocked transfer', () => {
const witness = encodeWitness()
const receipts = ReceivePolicyReceipt.fromTransactionReceipt({
logs: [blockedLog(witness)],
})
expect(receipts).toHaveLength(1)
expect(receipts[0]).toBe(witness)
})
test('multiple blocked transfers', () => {
const receipts = ReceivePolicyReceipt.fromTransactionReceipt({
logs: [
blockedLog(encodeWitness()),
blockedLog(encodeWitness({ kind: 1 })),
],
})
expect(receipts).toHaveLength(2)
expect(ReceivePolicyReceipt.decode(receipts[0]!).kind).toBe('transfer')
expect(ReceivePolicyReceipt.decode(receipts[1]!).kind).toBe('mint')
})
test('ignores unrelated logs', () => {
const receipts = ReceivePolicyReceipt.fromTransactionReceipt({
logs: [
{
data: '0x',
topics: [zeroHash],
},
blockedLog(encodeWitness()),
],
})
expect(receipts).toHaveLength(1)
})
test('behavior: no logs', () => {
expect(ReceivePolicyReceipt.fromTransactionReceipt({})).toEqual([])
expect(ReceivePolicyReceipt.fromTransactionReceipt({ logs: [] })).toEqual(
[],
)
})
})
test('exports', () => {
expect(Object.keys(ReceivePolicyReceipt)).toMatchInlineSnapshot(`
[
"decode",
"encode",
"from",
"fromLog",
"fromTransactionReceipt",
]
`)
})