Commit 380dc2e9 authored by Will Cory's avatar Will Cory

make the types better

parent c88e8607
...@@ -25,6 +25,7 @@ describe(`cli:${write.name}`, () => { ...@@ -25,6 +25,7 @@ describe(`cli:${write.name}`, () => {
value, value,
contract: ATTESTATION_STATION_ADDRESS, contract: ATTESTATION_STATION_ADDRESS,
rpcUrl, rpcUrl,
dataType: 'string',
}) })
expect(txHash.startsWith('0x')).toBe(true) expect(txHash.startsWith('0x')).toBe(true)
......
// constants // constants
export { ATTESTATION_STATION_ADDRESS } from './constants/attestationStationAddress' export { ATTESTATION_STATION_ADDRESS } from './constants/attestationStationAddress'
// lib // lib
export { readAttestation } from './lib/readAttestation' export {
readAttestation,
readAttestationAddress,
readAttestationBool,
readAttestationNumber,
readAttestationString,
} from './lib/readAttestation'
export { readAttestations } from './lib/readAttestations' export { readAttestations } from './lib/readAttestations'
export { prepareWriteAttestation } from './lib/prepareWriteAttestation' export { prepareWriteAttestation } from './lib/prepareWriteAttestation'
export { prepareWriteAttestations } from './lib/prepareWriteAttestations' export { prepareWriteAttestations } from './lib/prepareWriteAttestations'
export { writeAttestation } from './lib/writeAttestation' export { writeAttestation } from './lib/writeAttestation'
export { abi } from './lib/abi' export { abi } from './lib/abi'
export { parseAttestationBytes } from './lib/parseAttestationBytes'
export { stringifyAttestationBytes } from './lib/stringifyAttestationBytes' export { stringifyAttestationBytes } from './lib/stringifyAttestationBytes'
export {
parseAttestationBytes,
parseAddress,
parseNumber,
parseBool,
parseString,
} from './lib/parseAttestationBytes'
// types // types
export type { AttestationReadParams } from './types/AttestationReadParams' export type { AttestationReadParams } from './types/AttestationReadParams'
export type { WagmiBytes } from './types/WagmiBytes' export type { WagmiBytes } from './types/WagmiBytes'
......
...@@ -3,7 +3,13 @@ import { toUtf8Bytes } from 'ethers/lib/utils.js' ...@@ -3,7 +3,13 @@ import { toUtf8Bytes } from 'ethers/lib/utils.js'
import { expect, describe, it } from 'vitest' import { expect, describe, it } from 'vitest'
import { WagmiBytes } from '../types/WagmiBytes' import { WagmiBytes } from '../types/WagmiBytes'
import { parseAttestationBytes } from './parseAttestationBytes' import {
parseNumber,
parseAddress,
parseBool,
parseString,
parseAttestationBytes,
} from './parseAttestationBytes'
describe(parseAttestationBytes.name, () => { describe(parseAttestationBytes.name, () => {
it('works for strings', () => { it('works for strings', () => {
...@@ -15,7 +21,12 @@ describe(parseAttestationBytes.name, () => { ...@@ -15,7 +21,12 @@ describe(parseAttestationBytes.name, () => {
it('works for numbers', () => { it('works for numbers', () => {
const num = 123 const num = 123
const bytes = BigNumber.from(num).toHexString() as WagmiBytes const bytes = BigNumber.from(num).toHexString() as WagmiBytes
expect(parseAttestationBytes(bytes, 'number')).toBe(num.toString()) expect(parseAttestationBytes(bytes, 'number')).toMatchInlineSnapshot(`
{
"hex": "0x7b",
"type": "BigNumber",
}
`)
}) })
it('works for addresses', () => { it('works for addresses', () => {
...@@ -26,7 +37,7 @@ describe(parseAttestationBytes.name, () => { ...@@ -26,7 +37,7 @@ describe(parseAttestationBytes.name, () => {
it('works for booleans', () => { it('works for booleans', () => {
const bytes = BigNumber.from(1).toHexString() as WagmiBytes const bytes = BigNumber.from(1).toHexString() as WagmiBytes
expect(parseAttestationBytes(bytes, 'bool')).toBe('true') expect(parseAttestationBytes(bytes, 'bool')).toBe(true)
}) })
it('should work for raw bytes', () => { it('should work for raw bytes', () => {
...@@ -40,3 +51,28 @@ describe(parseAttestationBytes.name, () => { ...@@ -40,3 +51,28 @@ describe(parseAttestationBytes.name, () => {
expect(parseAttestationBytes(bytes, 'foo')).toBe(bytes) expect(parseAttestationBytes(bytes, 'foo')).toBe(bytes)
}) })
}) })
describe('parseFoo', () => {
it('works for strings', () => {
const str = 'Hello World'
const bytes = BigNumber.from(toUtf8Bytes(str)).toHexString() as WagmiBytes
expect(parseString(bytes)).toBe(str)
})
it('works for numbers', () => {
const num = 123
const bytes = BigNumber.from(num).toHexString() as WagmiBytes
expect(parseNumber(bytes)).toEqual(BigNumber.from(num))
})
it('works for addresses', () => {
const addr = '0x1234567890123456789012345678901234567890'
const bytes = BigNumber.from(addr).toHexString() as WagmiBytes
expect(parseAddress(bytes)).toBe(addr)
})
it('works for booleans', () => {
const bytes = BigNumber.from(1).toHexString() as WagmiBytes
expect(parseBool(bytes)).toBe(true)
})
})
import { BigNumber } from 'ethers' import { BigNumber } from 'ethers'
import { toUtf8String } from 'ethers/lib/utils.js' import { toUtf8String } from 'ethers/lib/utils.js'
import type { Address } from '@wagmi/core'
import type { DataTypeOption } from '../types/DataTypeOption' import type { DataTypeOption } from '../types/DataTypeOption'
import type { WagmiBytes } from '../types/WagmiBytes' import type { WagmiBytes } from '../types/WagmiBytes'
import { ParseBytesReturn } from '../types/ParseBytesReturn'
export const parseAttestationBytes = ( /**
* Parses a string attestion
*/
export const parseString = (rawAttestation: WagmiBytes): string => {
rawAttestation = rawAttestation === '0x' ? '0x0' : rawAttestation
return rawAttestation ? toUtf8String(rawAttestation) : ''
}
/**
* Parses a boolean attestion
*/
export const parseBool = (rawAttestation: WagmiBytes): boolean => {
rawAttestation = rawAttestation === '0x' ? '0x0' : rawAttestation
return rawAttestation ? BigNumber.from(rawAttestation).gt(0) : false
}
/**
* Parses a number attestion
*/
export const parseNumber = (rawAttestation: WagmiBytes): BigNumber => {
rawAttestation = rawAttestation === '0x' ? '0x0' : rawAttestation
return rawAttestation ? BigNumber.from(rawAttestation) : BigNumber.from(0)
}
/**
* Parses a address attestion
*/
export const parseAddress = (rawAttestation: WagmiBytes): Address => {
rawAttestation = rawAttestation === '0x' ? '0x0' : rawAttestation
return rawAttestation
? (BigNumber.from(rawAttestation).toHexString() as Address)
: '0x0000000000000000000000000000000000000000'
}
/**
* Parses a raw attestation
*/
export const parseAttestationBytes = <TDataType extends DataTypeOption>(
attestationBytes: WagmiBytes, attestationBytes: WagmiBytes,
dataType: DataTypeOption dataType: TDataType
) => { ): ParseBytesReturn<TDataType> => {
if (dataType === 'bytes') { if (dataType === 'bytes') {
return attestationBytes return attestationBytes as ParseBytesReturn<TDataType>
} }
if (dataType === 'number') { if (dataType === 'number') {
return BigNumber.from(attestationBytes).toString() return parseNumber(attestationBytes) as ParseBytesReturn<TDataType>
} }
if (dataType === 'address') { if (dataType === 'address') {
return BigNumber.from(attestationBytes).toHexString() return parseAddress(attestationBytes) as ParseBytesReturn<TDataType>
} }
if (dataType === 'bool') { if (dataType === 'bool') {
return BigNumber.from(attestationBytes).gt(0) ? 'true' : 'false' return parseBool(attestationBytes) as ParseBytesReturn<TDataType>
} }
if (dataType === 'string') { if (dataType === 'string') {
return attestationBytes && toUtf8String(attestationBytes) return parseString(attestationBytes) as ParseBytesReturn<TDataType>
} }
console.warn(`unrecognized dataType ${dataType satisfies never}`) console.warn(`unrecognized dataType ${dataType satisfies never}`)
return attestationBytes return attestationBytes as never
} }
...@@ -39,3 +39,4 @@ describe(readAttestation.name, () => { ...@@ -39,3 +39,4 @@ describe(readAttestation.name, () => {
) )
}) })
}) })
import type { Address } from '@wagmi/core' import type { Address } from '@wagmi/core'
import { BigNumber } from 'ethers'
import { DataTypeOption, DEFAULT_DATA_TYPE } from '../types/DataTypeOption' import { DataTypeOption } from '../types/DataTypeOption'
import { ParseBytesReturn } from '../types/ParseBytesReturn'
import { readAttestations } from './readAttestations' import { readAttestations } from './readAttestations'
/** /**
...@@ -17,19 +19,166 @@ import { readAttestations } from './readAttestations' ...@@ -17,19 +19,166 @@ import { readAttestations } from './readAttestations'
* key: 'my_key', * key: 'my_key',
* }, * },
*/ */
export const readAttestation = async ( export const readAttestation = async <TDataType extends DataTypeOption>(
/**
* Creator of the attestation
*/
creator: Address, creator: Address,
/**
* Address the attestation is about
*/
about: Address, about: Address,
/**
* Key of the attestation
*/
key: string, key: string,
dataType: DataTypeOption = DEFAULT_DATA_TYPE, /**
* Data type of the attestation
* string | bool | number | address | bytes
*
* @defaults 'string'
*/
dataType: TDataType,
/**
* Attestation address
* defaults to the official Optimism attestation station determistic deploy address
*
* @defaults '0xEE36eaaD94d1Cc1d0eccaDb55C38bFfB6Be06C77'
*/
contractAddress: Address = '0xEE36eaaD94d1Cc1d0eccaDb55C38bFfB6Be06C77' contractAddress: Address = '0xEE36eaaD94d1Cc1d0eccaDb55C38bFfB6Be06C77'
) => { ): Promise<ParseBytesReturn<TDataType>> => {
const [result] = await readAttestations({ const [result] = await readAttestations({
creator, creator,
about, about,
key, key,
dataType,
contractAddress, contractAddress,
dataType,
}) })
return result return result as ParseBytesReturn<TDataType>
}
/**
* Reads a string attestation
*/
export const readAttestationString = (
/**
* Creator of the attestation
*/
creator: Address,
/**
* Address the attestation is about
*/
about: Address,
/**
* Key of the attestation
*/
key: string,
/**
* Attestation address
* defaults to the official Optimism attestation station determistic deploy address
*
* @defaults '0xEE36eaaD94d1Cc1d0eccaDb55C38bFfB6Be06C77'
*/
contractAddress: Address = '0xEE36eaaD94d1Cc1d0eccaDb55C38bFfB6Be06C77'
) => {
return readAttestation(
creator,
about,
key,
'string',
contractAddress
) as Promise<string>
}
export const readAttestationBool = (
/**
* Creator of the attestation
*/
creator: Address,
/**
* Address the attestation is about
*/
about: Address,
/**
* Key of the attestation
*/
key: string,
/**
* Attestation address
* defaults to the official Optimism attestation station determistic deploy address
*
* @defaults '0xEE36eaaD94d1Cc1d0eccaDb55C38bFfB6Be06C77'
*/
contractAddress: Address = '0xEE36eaaD94d1Cc1d0eccaDb55C38bFfB6Be06C77'
) => {
return readAttestation(
/**
* Creator of the attestation
*/
creator,
about,
key,
'bool',
contractAddress
) as Promise<boolean>
}
export const readAttestationNumber = (
/**
* Creator of the attestation
*/
creator: Address,
/**
* Address the attestation is about
*/
about: Address,
/**
* Key of the attestation
*/
key: string,
/**
* Attestation address
* defaults to the official Optimism attestation station determistic deploy address
*
* @defaults '0xEE36eaaD94d1Cc1d0eccaDb55C38bFfB6Be06C77'
*/
contractAddress: Address = '0xEE36eaaD94d1Cc1d0eccaDb55C38bFfB6Be06C77'
) => {
return readAttestation(
creator,
about,
key,
'number',
contractAddress
) as Promise<BigNumber>
}
export const readAttestationAddress = (
/**
* Creator of the attestation
*/
creator: Address,
/**
* Address the attestation is about
*/
about: Address,
/**
* Key of the attestation
*/
key: string,
/**
* Attestation address
* defaults to the official Optimism attestation station determistic deploy address
*
* @defaults '0xEE36eaaD94d1Cc1d0eccaDb55C38bFfB6Be06C77'
*/
contractAddress: Address = '0xEE36eaaD94d1Cc1d0eccaDb55C38bFfB6Be06C77'
) => {
return readAttestation(
creator,
about,
key,
'address',
contractAddress
) as Promise<Address>
} }
...@@ -52,9 +52,12 @@ describe(readAttestation.name, () => { ...@@ -52,9 +52,12 @@ describe(readAttestation.name, () => {
` `
[ [
"https://assets.optimism.io/4a609661-6774-441f-9fdb-453fdbb89931-bucket/optimist-nft/attributes", "https://assets.optimism.io/4a609661-6774-441f-9fdb-453fdbb89931-bucket/optimist-nft/attributes",
"true", true,
"0x68747470733a2f2f6173736574732e6f7074696d69736d2e696f2f34613630393636312d363737342d343431662d396664622d3435336664626238393933312d6275636b65742f6f7074696d6973742d6e66742f61747472696275746573", "0x68747470733a2f2f6173736574732e6f7074696d69736d2e696f2f34613630393636312d363737342d343431662d396664622d3435336664626238393933312d6275636b65742f6f7074696d6973742d6e66742f61747472696275746573",
"9665973469795080068873111198635018086067645613429821071805084917303478255842407465257371959707311987533859075426222329066766033171696373249109388415320911537042272090516917683029511016473045453921068327933733922308146003731827", {
"hex": "0x68747470733a2f2f6173736574732e6f7074696d69736d2e696f2f34613630393636312d363737342d343431662d396664622d3435336664626238393933312d6275636b65742f6f7074696d6973742d6e66742f61747472696275746573",
"type": "BigNumber",
},
] ]
` `
) )
......
import { BigNumber } from 'ethers'
import { Address } from 'wagmi'
import { DataTypeOption } from './DataTypeOption'
import { WagmiBytes } from './WagmiBytes'
/**
* @internal
* Returns the correct typescript type of a DataOption
*/
export type ParseBytesReturn<T extends DataTypeOption> = T extends 'bytes'
? WagmiBytes
: T extends 'number'
? BigNumber
: T extends 'address'
? Address
: T extends 'bool'
? boolean
: T extends 'string'
? string
: never
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment