-
-
Notifications
You must be signed in to change notification settings - Fork 40
Expand file tree
/
Copy patherc20Streaming.ts
More file actions
122 lines (106 loc) · 4 KB
/
Copy patherc20Streaming.ts
File metadata and controls
122 lines (106 loc) · 4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import { type BytesLike, bytesToHex, isHexString } from '@metamask/utils';
import {
defaultOptions,
prepareResult,
type EncodingOptions,
type ResultValue,
} from '../returns';
import type { Hex } from '../types';
import { toHexString } from '../utils';
// Upper bound for timestamps (January 1, 10000 CE)
const TIMESTAMP_UPPER_BOUND_SECONDS = 253402300799;
/**
* Terms for configuring a linear streaming allowance of ERC20 tokens.
*/
export type ERC20StreamingTerms = {
/** The address of the ERC20 token contract. */
tokenAddress: BytesLike;
/** The initial amount available immediately. */
initialAmount: bigint;
/** The maximum total amount that can be transferred. */
maxAmount: bigint;
/** The rate at which allowance increases per second. */
amountPerSecond: bigint;
/** Unix timestamp when streaming begins. */
startTime: number;
};
/**
* Creates terms for the ERC20Streaming caveat, configuring a linear
* streaming allowance of ERC20 tokens.
*
* @param terms - The terms for the ERC20Streaming caveat.
* @param encodingOptions - The encoding options for the result.
* @returns Hex-encoded terms for the caveat (160 bytes).
* @throws Error if tokenAddress is invalid.
* @throws Error if initialAmount is negative.
* @throws Error if maxAmount is not positive.
* @throws Error if maxAmount is less than initialAmount.
* @throws Error if amountPerSecond is not positive.
* @throws Error if startTime is not positive.
* @throws Error if startTime exceeds upper bound.
*/
export function createERC20StreamingTerms(
terms: ERC20StreamingTerms,
encodingOptions?: EncodingOptions<'hex'>,
): Hex;
export function createERC20StreamingTerms(
terms: ERC20StreamingTerms,
encodingOptions: EncodingOptions<'bytes'>,
): Uint8Array;
/**
* Creates terms for the ERC20Streaming caveat, configuring a linear
* streaming allowance of ERC20 tokens.
*
* @param terms - The terms for the ERC20Streaming caveat.
* @param encodingOptions - The encoding options for the result.
* @returns The terms as a 160-byte hex string.
* @throws Error if any of the parameters are invalid.
*/
export function createERC20StreamingTerms(
terms: ERC20StreamingTerms,
encodingOptions: EncodingOptions<ResultValue> = defaultOptions,
): Hex | Uint8Array {
const { tokenAddress, initialAmount, maxAmount, amountPerSecond, startTime } =
terms;
if (!tokenAddress) {
throw new Error('Invalid tokenAddress: must be a valid address');
}
let prefixedTokenAddressHex: string;
if (typeof tokenAddress === 'string') {
if (!isHexString(tokenAddress) || tokenAddress.length !== 42) {
throw new Error('Invalid tokenAddress: must be a valid address');
}
prefixedTokenAddressHex = tokenAddress;
} else {
if (tokenAddress.length !== 20) {
throw new Error('Invalid tokenAddress: must be a valid address');
}
prefixedTokenAddressHex = bytesToHex(tokenAddress);
}
if (initialAmount < 0n) {
throw new Error('Invalid initialAmount: must be greater than zero');
}
if (maxAmount <= 0n) {
throw new Error('Invalid maxAmount: must be a positive number');
}
if (maxAmount < initialAmount) {
throw new Error('Invalid maxAmount: must be greater than initialAmount');
}
if (amountPerSecond <= 0n) {
throw new Error('Invalid amountPerSecond: must be a positive number');
}
if (startTime <= 0) {
throw new Error('Invalid startTime: must be a positive number');
}
if (startTime > TIMESTAMP_UPPER_BOUND_SECONDS) {
throw new Error(
'Invalid startTime: must be less than or equal to 253402300799',
);
}
const initialAmountHex = toHexString({ value: initialAmount, size: 32 });
const maxAmountHex = toHexString({ value: maxAmount, size: 32 });
const amountPerSecondHex = toHexString({ value: amountPerSecond, size: 32 });
const startTimeHex = toHexString({ value: startTime, size: 32 });
const hexValue = `${prefixedTokenAddressHex}${initialAmountHex}${maxAmountHex}${amountPerSecondHex}${startTimeHex}`;
return prepareResult(hexValue, encodingOptions);
}