import { BigNumber , constants , utils } from "ethers" ; import BalanceTree from "./claim/balance-tree" ; export enum ClaimType { Airdrop = 0 , GnoOption = 1 , UserOption = 2 , Investor = 3 , Team = 4 , Advisor = 5 } export interface Claim { account : string ; type : ClaimType ; claimableAmount : BigNumber ; } export interface ProvenClaim extends Claim { index : number ; proof : string [ ] ; } export interface ProvenClaims { claims : ProvenClaim [ ] ; merkleRoot : string ; } export interface ExecutableClaim extends ProvenClaim { claimedAmount : BigNumber ; value ? : BigNumber ; } export function claimHash ( index , { account , type , claimableAmount } ) { return Buffer . from ( utils . solidityKeccak256 ( [ "uint256" , "uint8" , "address" , "uint256" ] , [ index , type , account , claimableAmount ] ) . substr ( 2 ) , "hex" ) ; } const claimInputEntries = [ "index" , "type" , "account" , "claimableAmount" , "claimedAmount" , "proof" , ] as const ; type MapIntoExecutableClaim < T > = T extends readonly [ infer U , ... infer Rest ] ? U extends keyof ExecutableClaim ? [ ExecutableClaim [ U ] , ... MapIntoExecutableClaim < Rest > ] : never : [ ] ; export type ClaimInput = MapIntoExecutableClaim < typeof claimInputEntries > ; type ArrayToVecArray < T > = T extends readonly [ infer U , ... infer Rest ] ? [ U [ ] , ... ArrayToVecArray < Rest > ] : [ ] ; export type ClaimManyInput = [ ... ArrayToVecArray < ClaimInput > , BigNumber [ ] ] ; export function getClaimInput ( claim ) { return claimInputEntries . map ( ( entry ) => claim [ entry ] ) as ClaimInput ; } export function getClaimManyInput ( claims ) { return [ ... ( claimInputEntries . map ( ( entry ) => claims . map ( ( claim ) => claim [ entry ] ) ) as ArrayToVecArray < ClaimInput > ) , claims . map ( ( { value } ) => value ?? constants . Zero ) , ] ; } export function computeProofs ( claims ) { const sortedClaims = claims . map ( ( claim , indexBeforeSorting ) => ( { ... claim , indexBeforeSorting } ) ) . sort ( ( { account : lhs } , { account : rhs } ) => lhs == rhs ? 0 : lhs . toLowerCase ( ) < rhs . toLowerCase ( ) ? - 1 : 1 ) ; const tree = new BalanceTree ( sortedClaims ) ; const provenClaims = sortedClaims . map ( ( claim , index ) => ( { ... claim , index , proof : tree . getProof ( index , claim ) , } ) ) . sort ( ( { indexBeforeSorting : lhs } , { indexBeforeSorting : rhs } ) => lhs - rhs ) ; provenClaims . forEach ( ( claim ) => delete ( claim as { indexBeforeSorting ? : number ; } ) . indexBeforeSorting ) ; return { claims : provenClaims , merkleRoot : tree . getHexRoot ( ) , } ; }