punkkit-sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/.env +47 -0
  2. package/.gitmodules +3 -0
  3. package/README.md +158 -0
  4. package/config/auction.config.ts +40 -0
  5. package/config/env.config.ts +204 -0
  6. package/config/uniswap.config.ts +107 -0
  7. package/config/voucher.config.ts +10 -0
  8. package/contracts/MutiVoucher.sol +78 -0
  9. package/contracts/auction/ChainXAuction.sol +177 -0
  10. package/contracts/auction/ChainXAuctionV2.sol +672 -0
  11. package/contracts/auction/ChainXWrappedETH.sol +80 -0
  12. package/contracts/auction/ChainYLiquidityManager.sol +57 -0
  13. package/contracts/auction/ChainYShadowETH.sol +148 -0
  14. package/contracts/auction/ChainYVault.sol +195 -0
  15. package/contracts/auction/ChainYVaultCoinbase.sol +276 -0
  16. package/contracts/auction/ChainYVaultV2.sol +318 -0
  17. package/contracts/auction/coinbase-and-stake/README.md +55 -0
  18. package/contracts/auction/coinbase-and-stake/coinbase.sol +142 -0
  19. package/contracts/auction/coinbase-and-stake/invokeCoinbase.sol +159 -0
  20. package/contracts/auction/coinbase-and-stake/invokeStake.sol +82 -0
  21. package/contracts/auction/coinbase-and-stake/stake.sol +92 -0
  22. package/contracts/auction/interfaces/IUniswapV2Factory.sol +15 -0
  23. package/contracts/auction/interfaces/IUniswapV2Pair.sol +53 -0
  24. package/contracts/auction/interfaces/IUniswapV2Router02.sol +25 -0
  25. package/contracts/auction/interfaces/IUnlockStrategy.sol +18 -0
  26. package/contracts/auction/libraries/EventParser.sol +32 -0
  27. package/contracts/auction/libraries/TransactionParser.sol +70 -0
  28. package/contracts/auction/strategies/MatchResultWithdrawnStrategy.sol +33 -0
  29. package/contracts/auction/utils/BytesLib.sol +180 -0
  30. package/contracts/auction/utils/RLPReader.sol +355 -0
  31. package/contracts/uniswap/Create2.sol +80 -0
  32. package/contracts/uniswap/DynamicFee.sol +100 -0
  33. package/contracts/uniswap/Example.sol +35 -0
  34. package/contracts/uniswap/HookMiner.sol +52 -0
  35. package/contracts/uniswap/LimitOrder.sol +486 -0
  36. package/contracts/uniswap/LiquidPool.sol +179 -0
  37. package/contracts/uniswap/MockERC20.sol +20 -0
  38. package/hardhat.config.ts +35 -0
  39. package/ignition/modules/LimitOrder.ts +33 -0
  40. package/package.json +32 -0
  41. package/scripts/auction/deploy.ts +23 -0
  42. package/scripts/auction/deployCoinbase.ts +21 -0
  43. package/scripts/auction/deployXAuction.ts +23 -0
  44. package/scripts/auction/deployYVault.ts +22 -0
  45. package/scripts/deploy_voucher.ts +20 -0
  46. package/scripts/uniswap/deploy/deploy.ts +65 -0
  47. package/scripts/uniswap/deploy/deploy_create2.ts +11 -0
  48. package/scripts/uniswap/deploy/deploy_example.ts +35 -0
  49. package/scripts/uniswap/deploy/deploy_hooks.ts +74 -0
  50. package/scripts/uniswap/deploy/deploy_mockERC20.ts +42 -0
  51. package/scripts/uniswap/deploy/help.ts +96 -0
  52. package/scripts/uniswap/deploy/init.ts +70 -0
  53. package/src/auction/chainXAuction.ts +209 -0
  54. package/src/auction/chainYVault.ts +153 -0
  55. package/src/auction/event.ts +19 -0
  56. package/src/auction/serialize.ts +162 -0
  57. package/src/auction/type.ts +71 -0
  58. package/src/lib/signer.ts +20 -0
  59. package/src/lib/unlock.ts +14 -0
  60. package/src/uniswap/1-marketprice/addLiquidity.ts +80 -0
  61. package/src/uniswap/1-marketprice/removeLiquidity.ts +63 -0
  62. package/src/uniswap/1-marketprice/swap.ts +100 -0
  63. package/src/uniswap/2-limitorder/kill.ts +70 -0
  64. package/src/uniswap/2-limitorder/place.ts +93 -0
  65. package/src/uniswap/2-limitorder/withdraw.ts +78 -0
  66. package/src/uniswap/3-dynamicfee/dynamicfee.ts +321 -0
  67. package/src/uniswap/lib/ERC20.ts +49 -0
  68. package/src/uniswap/lib/contract.ts +18 -0
  69. package/src/uniswap/lib/limitOrder.ts +40 -0
  70. package/src/uniswap/lib/liqCalculation.ts +152 -0
  71. package/src/uniswap/lib/listen.ts +57 -0
  72. package/src/uniswap/lib/pool.ts +62 -0
  73. package/src/uniswap/lib/swap.ts +8 -0
  74. package/src/uniswap/lib/types.ts +21 -0
  75. package/src/uniswap/lib/utils.ts +26 -0
  76. package/src/uniswap/playgroud/abiencode.ts +21 -0
  77. package/src/uniswap/playgroud/amount0.ts +47 -0
  78. package/src/uniswap/playgroud/errordecode.ts +54 -0
  79. package/src/uniswap/playgroud/errorsigs.ts +86 -0
  80. package/src/voucher.ts +122 -0
  81. package/test/auction/ChainXAuctionV2.test.ts +265 -0
  82. package/test/auction/ChainYVaultV2.test.js +163 -0
  83. package/test/auction/ChainYVaultV2.test.ts +183 -0
  84. package/test/auction/auction.test.ts +106 -0
  85. package/test/connect_punk.test.ts +26 -0
  86. package/test/create2.test.ts +44 -0
  87. package/test/normal.ts +43 -0
  88. package/test/test-config.ts +18 -0
  89. package/test/uniswap/example.test.ts +62 -0
  90. package/test/uniswap/limitOrder.test.ts +184 -0
  91. package/test/uniswap/mockERC20.test.ts +142 -0
  92. package/test/voucher_hardhat.test.ts +120 -0
  93. package/test/voucher_punk.test.ts +83 -0
  94. package/tsconfig.json +11 -0
@@ -0,0 +1,62 @@
1
+ import { ethers } from "hardhat";
2
+ import type { Contract } from "ethers";
3
+ import { PoolKey, ModifyPositionParams } from "./types";
4
+
5
+ export async function modifyPosition(contract: Contract, modifyPositionParams: ModifyPositionParams, hookData: string) {
6
+ // Add liquidity
7
+ const tx = await contract.addLiquidity(modifyPositionParams, hookData);
8
+ await tx.wait();
9
+ }
10
+
11
+ // Function to get Pool ID
12
+ export function getPoolId(poolKey: PoolKey): string {
13
+ ;
14
+ return ethers.utils.keccak256(ethers.utils.solidityPack(
15
+ ["bytes"],
16
+ [ethers.utils.defaultAbiCoder.encode(
17
+ ["address", "address", "uint24", "int24", "address"],
18
+ [poolKey.currency0, poolKey.currency1, poolKey.fee, poolKey.tickSpacing, poolKey.hooks]
19
+ )]
20
+ ));
21
+ }
22
+
23
+ // Function to get Slot0 of the Pool
24
+ async function getSlot0(contract: Contract) {
25
+ const slot0 = await contract.getSlot0();
26
+ // console.log(`Returned slot0: ${JSON.stringify(slot0)}`);
27
+ return slot0;
28
+ }
29
+
30
+ // Function to get Liquidity of the Pool
31
+ export async function getLiquidity(contract: Contract, poolKey: PoolKey) {
32
+ const poolId = getPoolId(poolKey);
33
+ console.log(`PoolId: ${poolId}`);
34
+
35
+ const liquidity = await contract.getLiquidity(poolId);
36
+ console.log(`Returned liquidity: ${liquidity}`);
37
+ return liquidity;
38
+ }
39
+
40
+ export async function getPoolSqrtPrice(liqPool: Contract): Promise<bigint> {
41
+ const slot0 = await getSlot0(liqPool);
42
+ return slot0[0].toBigInt();
43
+ }
44
+
45
+ // Function to get Pool Price
46
+ export async function getPoolPrice(liqPool: Contract): Promise<number> {
47
+ const slot0 = await getSlot0(liqPool);
48
+ const q96 = 2n ** 96n;
49
+ // slot0 type is @BigNumber
50
+ const sqrtPriceX96:bigint = slot0[0].toBigInt();
51
+
52
+ const priceX1e18 = (sqrtPriceX96 * sqrtPriceX96 * (10n ** 18n)) / (q96 * q96);
53
+ const result = Number(priceX1e18) / 10**18;
54
+ // console.log("price:", result.toString());
55
+ return result;
56
+ }
57
+
58
+ export async function getCurrentTick(liqPool: Contract): Promise<number> {
59
+ const slot0 = await getSlot0(liqPool);
60
+ const tick: number = slot0[1];
61
+ return tick;
62
+ }
@@ -0,0 +1,8 @@
1
+ import { Contract } from "ethers";
2
+ import { SwapParams } from "./types";
3
+
4
+ export async function executeSwap(contract: Contract, swapParams: SwapParams, hookData: string) {
5
+ let tx = await contract.executeSwap(swapParams, hookData);
6
+ await tx.wait();
7
+ console.log("Swap executed successfully");
8
+ }
@@ -0,0 +1,21 @@
1
+
2
+ export interface PoolKey {
3
+ currency0: string;
4
+ currency1: string;
5
+ fee: number;
6
+ tickSpacing: number;
7
+ hooks: string;
8
+ }
9
+
10
+ export interface SwapParams {
11
+ zeroForOne: boolean;
12
+ amountSpecified: bigint;
13
+ sqrtPriceLimitX96: bigint;
14
+ }
15
+
16
+ export interface ModifyPositionParams {
17
+ tickLower: number; // 流动性生效最低价格
18
+ tickUpper: number; // 流动性生效最高价格
19
+ liquidityDelta: bigint;
20
+ salt?:string;
21
+ }
@@ -0,0 +1,26 @@
1
+ // JsonRpcProvider is runtime object
2
+ import { JsonRpcProvider } from "@ethersproject/providers";
3
+ import { ethers } from "hardhat"
4
+
5
+ export async function isDeployed(provider: JsonRpcProvider, address: string) {
6
+ let code = await provider.getCode(address);
7
+ // console.log("code =", code);
8
+ return code !== "0x";
9
+ }
10
+
11
+ export function bigintToBytes32(value : bigint): string {
12
+ return ethers.utils.id(value.toString());
13
+ }
14
+
15
+ // Function to encode the parameters
16
+ export function abiEncode(types: string[], values: any[]): string {
17
+ const abiCoder = ethers.utils.defaultAbiCoder;
18
+ const encodedParams = abiCoder.encode(types, values);
19
+ return encodedParams;
20
+ }
21
+
22
+ export function bytecodeWithArgs(bytecode: string, types: string[], params: any[]): string {
23
+ const encodedParams = abiEncode(types, params);
24
+ const initCode = ethers.utils.hexConcat([bytecode, encodedParams]);
25
+ return initCode;
26
+ }
@@ -0,0 +1,21 @@
1
+ import { ethers } from "hardhat";
2
+ import { ModifyPositionParams } from "../lib/types";
3
+
4
+ // Example ModifyLiquidityParams
5
+ const positionParams: ModifyPositionParams = {
6
+ tickLower: 84222,
7
+ tickUpper: 86129,
8
+ liquidityDelta: BigInt("1517882343751509868544"),
9
+ salt: ethers.utils.keccak256("0x00")
10
+ };
11
+
12
+ // Example hookData as a hex string
13
+ const hookData = "0x10";
14
+
15
+ // Get ABI encoding
16
+ const encodedData = ethers.utils.defaultAbiCoder.encode(
17
+ ["tuple(int24,int24,int256,bytes32)", "bytes"],
18
+ [positionParams, hookData]
19
+ );
20
+
21
+ console.log("Encoded Data:", encodedData);
@@ -0,0 +1,47 @@
1
+ import { BigNumber } from 'ethers';
2
+ import { amount0 } from '../lib/liqCalculation';
3
+
4
+ // FullMath.mulDivRoundingUp: Multiplies two numbers and divides the result by a denominator, rounding up
5
+ function mulDivRoundingUp(a: BigNumber, b: BigNumber, denominator: BigNumber): BigNumber {
6
+ const product = a.mul(b);
7
+ const remainder = product.mod(denominator);
8
+ const quotient = product.div(denominator);
9
+ return remainder.isZero() ? quotient : quotient.add(1);
10
+ }
11
+
12
+ // UnsafeMath.divRoundingUp: Divides two numbers, rounding up
13
+ function divRoundingUp(a: BigNumber, b: BigNumber): BigNumber {
14
+ const remainder = a.mod(b);
15
+ const quotient = a.div(b);
16
+ return remainder.isZero() ? quotient : quotient.add(1);
17
+ }
18
+
19
+ // Example usage
20
+ function calculateAmount0Delta(
21
+ numerator1: BigNumber,
22
+ numerator2: BigNumber,
23
+ sqrtPriceBX96: BigNumber,
24
+ sqrtPriceAX96: BigNumber
25
+ ): BigNumber {
26
+ // Equivalent to the Solidity code snippet
27
+ return divRoundingUp(mulDivRoundingUp(numerator1, numerator2, sqrtPriceBX96), sqrtPriceAX96);
28
+ }
29
+
30
+ // Define the FixedPoint96 resolution (2^96)
31
+ const FixedPoint96_RESOLUTION = BigNumber.from(2).pow(96);
32
+
33
+ // Example values for liquidity, sqrtPriceAX96, and sqrtPriceBX96
34
+ // ref: test/libraries/SqrtPriceMath.t.sol, test_swapComputation_sqrtPTimessqrtQOverflows, line 337
35
+ const liquidity = BigNumber.from("50015962439936049619261659728067971248"); // Example value
36
+ const sqrtPriceAX96 = BigNumber.from("1025574284609383582644711336373707553698163132913"); // Example value
37
+ const sqrtPriceBX96 = BigNumber.from("1025574284609383690408304870162715216695788925244"); // Example value
38
+
39
+ // Calculate numerator1 and numerator2
40
+ const numerator1 = liquidity.mul(FixedPoint96_RESOLUTION); // This is equivalent to shifting left by the FixedPoint96 resolution
41
+ const numerator2 = sqrtPriceBX96.sub(sqrtPriceAX96);
42
+
43
+ const result = calculateAmount0Delta(numerator1, numerator2, sqrtPriceBX96, sqrtPriceAX96);
44
+ console.log(result.toString());
45
+
46
+ const result2 = amount0(liquidity.toBigInt(), sqrtPriceBX96.toBigInt(), sqrtPriceAX96.toBigInt());
47
+ console.log(result2.toString());
@@ -0,0 +1,54 @@
1
+ import { ethers } from "ethers";
2
+
3
+ interface DecodedData {
4
+ functionSelector: string;
5
+ address: string;
6
+ fixedInteger: number;
7
+ offset: number;
8
+ errorFunctionSelector: string;
9
+ stringLength: number;
10
+ stringData: string;
11
+ }
12
+
13
+ function hexToString(hex: string): string {
14
+ // Remove the '0x' prefix if present
15
+ hex = hex.replace(/^0x/, '');
16
+
17
+ // Convert hex to bytes
18
+ const bytes = Buffer.from(hex, 'hex');
19
+
20
+ // Convert bytes to string using UTF-8 encoding
21
+ return bytes.toString('utf8');
22
+ }
23
+
24
+ function decodeData(encodedData: string): DecodedData {
25
+ const functionSelector = encodedData.slice(0, 10);
26
+ const address = `0x${encodedData.slice(34, 74)}`;
27
+ const fixedInteger = parseInt(encodedData.slice(74, 138), 16);
28
+ const offset = parseInt(encodedData.slice(138, 202), 16);
29
+ let errorFunctionSelector, stringLength, stringData;
30
+ if (offset != 0 ) {
31
+ errorFunctionSelector = `0x${encodedData.slice(202, 210)}`;
32
+ const offset = parseInt(encodedData.slice(210, 274), 16);
33
+ stringLength = parseInt(encodedData.slice(274, 338), 16);
34
+ stringData = hexToString(`0x${encodedData.slice(338, 338 + stringLength * 2)}`);
35
+ }
36
+
37
+ return {
38
+ functionSelector,
39
+ address,
40
+ fixedInteger,
41
+ offset,
42
+ errorFunctionSelector,
43
+ stringLength,
44
+ stringData
45
+ };
46
+ }
47
+
48
+ // Test the function with the provided data
49
+ const data1 = "0x319d54c3000000000000000000000000a1353ea8013d59ce815bf2fe7211e61e5519d0400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006408c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000c636f72726563742073616c74000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
50
+ const data2 = "0x319d54c3000000000000000000000000a1353ea8013d59ce815bf2fe7211e61e5519d0400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006408c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000a77726f6e672073616c740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
51
+ const data3 = "0x319d54c3000000000000000000000000867cd373c2567a10bc512f05771e55e73e67d0400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000429c3b7ee00000000000000000000000000000000000000000000000000000000";
52
+ const data4 = "0xb12c5f9c000000000000000000000000d9b3d09f662b3b5479a785ac6aba5dd17a132dc300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000064e450d38c0000000000000000000000004132f0bebb312245fd4c33d1177a617a98691040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006db11235f6ec6a4c0100000000000000000000000000000000000000000000000000000000"
53
+
54
+ console.log(decodeData(data4));
@@ -0,0 +1,86 @@
1
+ import { ethers } from "hardhat";
2
+
3
+ // Define an array of error signatures
4
+ // Error NotSelf(): 0x29c3b7ee
5
+ // Error HookAddressNotValid(address): 0xe65af6a0
6
+ // Error InvalidHookResponse(): 0x1e048e1d
7
+ // Error Wrap__FailedHookCall(address,bytes): 0x319d54c3
8
+ // Error ProtocolFeeCannotBeFetched(): 0x1ee49702
9
+ // Error AlreadyUnlocked(): 0x5090d6c6
10
+ // Error NotPoolManager(): 0xae18210a
11
+ // Error CurrencyNotSettled: 0x5212cba1
12
+ // Error PoolAlreadyInitialized(): 0x7983c051
13
+ // Error PoolNotInitialized(): 0x486aa307
14
+ // Error PriceLimitAlreadyExceeded(uint160,uint160): 0x7c9c6e8f
15
+ // Error NonZeroNativeValue(): 0x19d245cf
16
+ // Error ERC20InsufficientBalance(address,uint256,uint256): 0xe450d38c
17
+ // Error ERC20InsufficientAllowance(address,uint256,uint256): 0xfb8f41b2
18
+ // Error Wrap__NativeTransferFailed(address,bytes): 0x8549db59
19
+ // Error Wrap__ERC20TransferFailed(address,bytes): 0xb12c5f9c
20
+ // Error NotPoolManager(): 0xae18210a
21
+ // Error NotFilled(): 0x6cb6fbf0
22
+ // Error InvalidFunc(bytes4): 0x1f8f8d4b
23
+ // Error ZeroLiquidity(): 0x10074548
24
+ // Error InRange(): 0x23ac68e7
25
+ // Error CrossedRange(): 0xb319920d
26
+ const errorSignatures = [
27
+ // Hooks.sol
28
+ 'NotSelf()',
29
+ 'HookAddressNotValid(address)',
30
+ 'InvalidHookResponse()',
31
+ 'Wrap__FailedHookCall(address,bytes)',
32
+
33
+ 'ProtocolFeeCannotBeFetched()',
34
+
35
+ // PoolManager.sol
36
+ 'AlreadyUnlocked()',
37
+ 'NotPoolManager()',
38
+ 'CurrencyNotSettled()',
39
+ 'PoolAlreadyInitialized()',
40
+ 'PoolNotInitialized()',
41
+ 'PriceLimitAlreadyExceeded(uint160,uint160)',
42
+ 'NonZeroNativeValue()',
43
+
44
+ // ERC20.sol
45
+ 'ERC20InsufficientBalance(address,uint256,uint256)',
46
+ 'ERC20InsufficientAllowance(address,uint256,uint256)',
47
+
48
+ 'Wrap__NativeTransferFailed(address,bytes)',
49
+ 'Wrap__ERC20TransferFailed(address,bytes)',
50
+
51
+ // SafeCallBack.sol
52
+ 'NotPoolManager()',
53
+
54
+ // LimitOrder.sol
55
+ 'NotFilled()',
56
+ 'InvalidFunc(bytes4)',
57
+ 'ZeroLiquidity()',
58
+ 'InRange()',
59
+ 'CrossedRange()',
60
+ ];
61
+
62
+ // FuncSig afterInitialize(address,PoolKey,uint160,int24,bytes): 0x105397c6
63
+ // FuncSig lockAcquiredPlace((address,address,uint24,int24,address),int24,bool,int256,address,bytes32): 0x3f3e517d
64
+ const funcSignatures = [
65
+ 'afterInitialize(address,PoolKey,uint160,int24,bytes)',
66
+
67
+ // LimitOrder.sol
68
+ 'lockAcquiredPlace((address,address,uint24,int24,address),int24,bool,int256,address,bytes32)'
69
+ ]
70
+
71
+ // Function to compute the function selector for an error signature
72
+ const computeFunctionSelector = (signature: string): string => {
73
+ const hash = ethers.keccak256(ethers.toUtf8Bytes(signature));
74
+ return hash.slice(0, 10); // "0x" + 8 hex characters
75
+ };
76
+
77
+ // Iterate over the error signatures and compute their function selectors
78
+ errorSignatures.forEach((signature) => {
79
+ const functionSelector = computeFunctionSelector(signature);
80
+ console.log(`Error ${signature}: ${functionSelector}`);
81
+ });
82
+
83
+ funcSignatures.forEach((signature) => {
84
+ const functionSelector = computeFunctionSelector(signature);
85
+ console.log(`FuncSig ${signature}: ${functionSelector}`);
86
+ });
package/src/voucher.ts ADDED
@@ -0,0 +1,122 @@
1
+ import {
2
+ BigNumber,
3
+ BigNumberish,
4
+ Contract,
5
+ ContractTransaction,
6
+ Signer,
7
+ providers,
8
+ utils,
9
+ } from "ethers";
10
+
11
+ import { MUTI_VOUCHER_ABI,MUTI_VOUCHER_ADDR } from "../config/voucher.config";
12
+
13
+
14
+ export const mutiVoucherABI = MUTI_VOUCHER_ABI.abi;
15
+
16
+ export type SignerOrProvider = Signer | providers.Provider;
17
+
18
+ export function getVoucherContract(
19
+ contractAddress: string,
20
+ signerOrProvider: SignerOrProvider
21
+ ): Contract {
22
+ return new Contract(contractAddress, mutiVoucherABI, signerOrProvider);
23
+ }
24
+
25
+ export async function createVoucher(
26
+ contractAddress: string,
27
+ signer: Signer,
28
+ name: string,
29
+ conversionRate: BigNumberish
30
+ ): Promise<ContractTransaction> {
31
+ const contract = getVoucherContract(contractAddress, signer);
32
+ return contract.createVoucher(name, conversionRate);
33
+ }
34
+
35
+ export async function getVoucherInfo(
36
+ contractAddress: string,
37
+ provider: SignerOrProvider,
38
+ name: string
39
+ ): Promise<BigNumber> {
40
+ const contract = getVoucherContract(contractAddress, provider);
41
+ return contract.getVoucherInfo(name);
42
+ }
43
+
44
+ export async function buyVoucher(
45
+ contractAddress: string,
46
+ signer: Signer,
47
+ name: string,
48
+ valueWei: BigNumberish
49
+ ): Promise<ContractTransaction> {
50
+ const contract = getVoucherContract(contractAddress, signer);
51
+ return contract.buy(name, { value: valueWei });
52
+ }
53
+
54
+ export async function buyVoucherWithEth(
55
+ contractAddress: string,
56
+ signer: Signer,
57
+ name: string,
58
+ valueEth: string
59
+ ): Promise<ContractTransaction> {
60
+ const valueWei = utils.parseEther(valueEth);
61
+ return buyVoucher(contractAddress, signer, name, valueWei);
62
+ }
63
+
64
+ // UseVoucher不是直接调用的
65
+ export async function useVoucher(
66
+ contractAddress: string,
67
+ signer: Signer,
68
+ name: string,
69
+ amount: BigNumberish
70
+ ): Promise<ContractTransaction> {
71
+ const contract = getVoucherContract(contractAddress, signer);
72
+ return contract.use(name, amount);
73
+ }
74
+
75
+ export async function balanceOf(
76
+ contractAddress: string,
77
+ provider: SignerOrProvider,
78
+ name: string,
79
+ user: string
80
+ ): Promise<BigNumber> {
81
+ const contract = getVoucherContract(contractAddress, provider);
82
+ return contract.balanceOf(name, user);
83
+ }
84
+
85
+ export async function getAllVouchers(
86
+ contractAddress: string,
87
+ provider: SignerOrProvider
88
+ ): Promise<string[]> {
89
+ const contract = getVoucherContract(contractAddress, provider);
90
+ return contract.getAllVouchers();
91
+ }
92
+
93
+ // 仅仅能够在punk链上使用
94
+ function buildUseVoucherPrefix(voucherNameBytes32: string): string {
95
+ const nameHex = utils.hexlify(voucherNameBytes32).replace(
96
+ /^0x/,
97
+ ""
98
+ );
99
+
100
+ if (nameHex.length > 64) {
101
+ throw new Error("Voucher name too long for 32 bytes");
102
+ }
103
+ const paddedName = nameHex.padEnd(64, "0");
104
+ console.log(paddedName)
105
+ return `0x0A0D03${paddedName}`;
106
+ }
107
+
108
+ // 仅仅能够在punk链上使用
109
+ export function BuildUseVoucherTx(
110
+ tx: providers.TransactionRequest,
111
+ voucherName: string
112
+ ): providers.TransactionRequest {
113
+ const prefix = buildUseVoucherPrefix(voucherName);
114
+ const rawData = tx.data ?? "0x";
115
+ const dataHex = utils.hexlify(rawData);
116
+ const mergedData = utils.hexConcat([prefix, dataHex]);
117
+
118
+ return {
119
+ ...tx,
120
+ data: mergedData,
121
+ };
122
+ }