infrastructure-upgrade/lib/v3-periphery/test/shared/path.ts

62 lines
1.8 KiB
TypeScript
Raw Normal View History

2023-04-08 21:46:18 +03:00
import { utils } from 'ethers'
import { FeeAmount } from './constants'
const ADDR_SIZE = 20
const FEE_SIZE = 3
const OFFSET = ADDR_SIZE + FEE_SIZE
const DATA_SIZE = OFFSET + ADDR_SIZE
export function encodePath(path: string[], fees: FeeAmount[]): string {
if (path.length != fees.length + 1) {
throw new Error('path/fee lengths do not match')
}
let encoded = '0x'
for (let i = 0; i < fees.length; i++) {
// 20 byte encoding of the address
encoded += path[i].slice(2)
// 3 byte encoding of the fee
encoded += fees[i].toString(16).padStart(2 * FEE_SIZE, '0')
}
// encode the final token
encoded += path[path.length - 1].slice(2)
return encoded.toLowerCase()
}
function decodeOne(tokenFeeToken: Buffer): [[string, string], number] {
// reads the first 20 bytes for the token address
const tokenABuf = tokenFeeToken.slice(0, ADDR_SIZE)
const tokenA = utils.getAddress('0x' + tokenABuf.toString('hex'))
// reads the next 2 bytes for the fee
const feeBuf = tokenFeeToken.slice(ADDR_SIZE, OFFSET)
const fee = feeBuf.readUIntBE(0, FEE_SIZE)
// reads the next 20 bytes for the token address
const tokenBBuf = tokenFeeToken.slice(OFFSET, DATA_SIZE)
const tokenB = utils.getAddress('0x' + tokenBBuf.toString('hex'))
return [[tokenA, tokenB], fee]
}
export function decodePath(path: string): [string[], number[]] {
let data = Buffer.from(path.slice(2), 'hex')
let tokens: string[] = []
let fees: number[] = []
let i = 0
let finalToken: string = ''
while (data.length >= DATA_SIZE) {
const [[tokenA, tokenB], fee] = decodeOne(data)
finalToken = tokenB
tokens = [...tokens, tokenA]
fees = [...fees, fee]
data = data.slice((i + 1) * OFFSET)
i += 1
}
tokens = [...tokens, finalToken]
return [tokens, fees]
}