@wireio/stake 0.2.4 → 0.2.5
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.
- package/lib/stake.browser.js +1678 -414
- package/lib/stake.browser.js.map +1 -1
- package/lib/stake.d.ts +49 -9
- package/lib/stake.js +1821 -497
- package/lib/stake.js.map +1 -1
- package/lib/stake.m.js +1678 -414
- package/lib/stake.m.js.map +1 -1
- package/package.json +1 -1
- package/src/assets/ethereum/ABI/outpost/Aggregator.sol/Aggregator.json +82 -0
- package/src/networks/ethereum/clients/deposit.client.ts +76 -2
- package/src/networks/ethereum/clients/pretoken.client.ts +130 -0
- package/src/networks/ethereum/clients/stake.client.ts +87 -24
- package/src/networks/ethereum/contract.ts +13 -0
- package/src/networks/ethereum/ethereum.ts +234 -88
- package/src/networks/ethereum/types.ts +2 -0
- package/src/networks/ethereum/utils.ts +314 -0
- package/src/staker/types.ts +62 -0
- package/src/types.ts +14 -1
package/package.json
CHANGED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_format": "hh-sol-artifact-1",
|
|
3
|
+
"contractName": "Aggregator",
|
|
4
|
+
"sourceName": "contracts/outpost/Aggregator.sol",
|
|
5
|
+
"abi": [
|
|
6
|
+
{
|
|
7
|
+
"inputs": [
|
|
8
|
+
{ "internalType": "address", "name": "_authority", "type": "address" },
|
|
9
|
+
{ "internalType": "int256", "name": "initialPrice", "type": "int256" },
|
|
10
|
+
{ "internalType": "uint8", "name": "__decimals", "type": "uint8" }
|
|
11
|
+
],
|
|
12
|
+
"name": "initialize",
|
|
13
|
+
"outputs": [],
|
|
14
|
+
"stateMutability": "nonpayable",
|
|
15
|
+
"type": "function"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"inputs": [],
|
|
19
|
+
"name": "decimals",
|
|
20
|
+
"outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }],
|
|
21
|
+
"stateMutability": "view",
|
|
22
|
+
"type": "function"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"inputs": [],
|
|
26
|
+
"name": "description",
|
|
27
|
+
"outputs": [{ "internalType": "string", "name": "", "type": "string" }],
|
|
28
|
+
"stateMutability": "pure",
|
|
29
|
+
"type": "function"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"inputs": [],
|
|
33
|
+
"name": "version",
|
|
34
|
+
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
|
|
35
|
+
"stateMutability": "pure",
|
|
36
|
+
"type": "function"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"inputs": [{ "internalType": "uint80", "name": "", "type": "uint80" }],
|
|
40
|
+
"name": "getRoundData",
|
|
41
|
+
"outputs": [
|
|
42
|
+
{ "internalType": "uint80", "name": "roundId", "type": "uint80" },
|
|
43
|
+
{ "internalType": "int256", "name": "answer", "type": "int256" },
|
|
44
|
+
{ "internalType": "uint256", "name": "startedAt", "type": "uint256" },
|
|
45
|
+
{ "internalType": "uint256", "name": "updatedAt", "type": "uint256" },
|
|
46
|
+
{ "internalType": "uint80", "name": "answeredInRound", "type": "uint80" }
|
|
47
|
+
],
|
|
48
|
+
"stateMutability": "view",
|
|
49
|
+
"type": "function"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"inputs": [],
|
|
53
|
+
"name": "latestRoundData",
|
|
54
|
+
"outputs": [
|
|
55
|
+
{ "internalType": "uint80", "name": "roundId", "type": "uint80" },
|
|
56
|
+
{ "internalType": "int256", "name": "answer", "type": "int256" },
|
|
57
|
+
{ "internalType": "uint256", "name": "startedAt", "type": "uint256" },
|
|
58
|
+
{ "internalType": "uint256", "name": "updatedAt", "type": "uint256" },
|
|
59
|
+
{ "internalType": "uint80", "name": "answeredInRound", "type": "uint80" }
|
|
60
|
+
],
|
|
61
|
+
"stateMutability": "view",
|
|
62
|
+
"type": "function"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"inputs": [{ "internalType": "int256", "name": "newPrice", "type": "int256" }],
|
|
66
|
+
"name": "updateAnswer",
|
|
67
|
+
"outputs": [],
|
|
68
|
+
"stateMutability": "nonpayable",
|
|
69
|
+
"type": "function"
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"inputs": [
|
|
73
|
+
{ "internalType": "int256", "name": "newPrice", "type": "int256" },
|
|
74
|
+
{ "internalType": "uint256", "name": "oldTimestamp", "type": "uint256" }
|
|
75
|
+
],
|
|
76
|
+
"name": "updateStale",
|
|
77
|
+
"outputs": [],
|
|
78
|
+
"stateMutability": "nonpayable",
|
|
79
|
+
"type": "function"
|
|
80
|
+
}
|
|
81
|
+
]
|
|
82
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { BigNumber, ethers } from "ethers";
|
|
2
|
-
import { DepositEvent, DepositResult } from "../types";
|
|
1
|
+
import { BigNumber, ethers, Signer } from "ethers";
|
|
2
|
+
import { DepositEvent, DepositResult, WithdrawRequestedEvent, WithdrawResult } from "../types";
|
|
3
3
|
import { EthereumContractService } from "../contract";
|
|
4
|
+
import { ChainID } from "@wireio/core";
|
|
4
5
|
|
|
5
6
|
export class DepositClient {
|
|
6
7
|
|
|
@@ -79,4 +80,77 @@ export class DepositClient {
|
|
|
79
80
|
}
|
|
80
81
|
|
|
81
82
|
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
async requestWithdraw(amountWei: BigNumber, signer: Signer, chainId: ChainID): Promise<WithdrawResult> {
|
|
86
|
+
// deadline is a period of time in the future that the signature is valid for
|
|
87
|
+
const deadline = Math.floor(Date.now() / 1000) + 3600;
|
|
88
|
+
|
|
89
|
+
const liqEth = this.contract.LiqEth;
|
|
90
|
+
const owner = await signer.getAddress();
|
|
91
|
+
|
|
92
|
+
const nonce: BigNumber = await liqEth.nonces(owner);
|
|
93
|
+
const domain = {
|
|
94
|
+
name: await liqEth.name(),
|
|
95
|
+
version: '1',
|
|
96
|
+
chainId,
|
|
97
|
+
verifyingContract: this.contract.LiqEth.address,
|
|
98
|
+
} as any;
|
|
99
|
+
|
|
100
|
+
const types = {
|
|
101
|
+
Permit: [
|
|
102
|
+
{ name: 'owner', type: 'address' },
|
|
103
|
+
{ name: 'spender', type: 'address' },
|
|
104
|
+
{ name: 'value', type: 'uint256' },
|
|
105
|
+
{ name: 'nonce', type: 'uint256' },
|
|
106
|
+
{ name: 'deadline', type: 'uint256' },
|
|
107
|
+
],
|
|
108
|
+
} as any;
|
|
109
|
+
|
|
110
|
+
const values = {
|
|
111
|
+
owner,
|
|
112
|
+
spender: this.contractService.getAddress('DepositManager'),
|
|
113
|
+
value: amountWei,
|
|
114
|
+
nonce: nonce,
|
|
115
|
+
deadline,
|
|
116
|
+
} as any;
|
|
117
|
+
|
|
118
|
+
const signature = await (signer as any)._signTypedData(domain, types, values);
|
|
119
|
+
const split = ethers.utils.splitSignature(signature);
|
|
120
|
+
|
|
121
|
+
const tx = await this.contract.DepositManager.requestWithdrawal(
|
|
122
|
+
amountWei,
|
|
123
|
+
deadline,
|
|
124
|
+
split.v,
|
|
125
|
+
split.r,
|
|
126
|
+
split.s
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
// wait for 1 confirmation
|
|
130
|
+
const receipt = await tx.wait(1);
|
|
131
|
+
|
|
132
|
+
// if WithdrawRequested event exists, parse it and get arguments
|
|
133
|
+
let withdrawRequested: WithdrawRequestedEvent | undefined;
|
|
134
|
+
const ev = receipt.events?.find((e) => e.event === 'WithdrawRequested');
|
|
135
|
+
|
|
136
|
+
if (ev && ev.args) {
|
|
137
|
+
const { user, ethAmount, nftId, readyAt } = ev.args;
|
|
138
|
+
withdrawRequested = {
|
|
139
|
+
user,
|
|
140
|
+
ethAmount: BigNumber.from(ethAmount),
|
|
141
|
+
nftId: BigNumber.from(nftId),
|
|
142
|
+
readyAt: readyAt,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return {
|
|
147
|
+
txHash: tx.hash,
|
|
148
|
+
receipt,
|
|
149
|
+
withdrawRequested,
|
|
150
|
+
} as WithdrawResult;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
|
|
82
156
|
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { BigNumber, ethers } from "ethers";
|
|
2
|
+
import { EthereumContractService } from "../contract";
|
|
3
|
+
import { formatContractErrors, sendOPPFinalize } from "../utils";
|
|
4
|
+
import { PurchaseAsset } from "../../../types";
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
export class PretokenClient {
|
|
9
|
+
private readonly contractService: EthereumContractService;
|
|
10
|
+
|
|
11
|
+
get contract() { return this.contractService.contract; }
|
|
12
|
+
|
|
13
|
+
constructor(contract: EthereumContractService) {
|
|
14
|
+
this.contractService = contract;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Purchase warrants by sending ETH to the Depositor.purchaseWarrantsWithETH(buyer) payable function.
|
|
21
|
+
* Returns txHash, receipt and parsed PurchasedWithETH event (if present).
|
|
22
|
+
*/
|
|
23
|
+
async purchaseWarrantsWithETH(amountWei: BigNumber, buyer: string): Promise<any> {
|
|
24
|
+
// attempt a simulation of the purchase call
|
|
25
|
+
try {
|
|
26
|
+
await this.contract.Depositor.callStatic.purchaseWarrantsWithETH(buyer, { value: amountWei });
|
|
27
|
+
} catch (err: any) {
|
|
28
|
+
let errorObj = formatContractErrors(err);
|
|
29
|
+
throw new Error(errorObj.name ?? errorObj.raw)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// attempt the real purchase call
|
|
33
|
+
let tx, receipt;
|
|
34
|
+
try {
|
|
35
|
+
tx = await this.contract.Depositor.purchaseWarrantsWithETH(buyer, { value: amountWei });
|
|
36
|
+
receipt = await tx.wait(1);
|
|
37
|
+
} catch (err: any) {
|
|
38
|
+
let errorObj = formatContractErrors(err);
|
|
39
|
+
throw new Error(errorObj.name ?? errorObj.raw)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
// Attempt to parse PurchasedWithETH event
|
|
44
|
+
let purchased: any | undefined;
|
|
45
|
+
const ev = receipt.events?.find((e) => e.event === 'PurchasedWithETH' || e.event === 'PurchasedWithETH(address,uint256,uint256,uint256)');
|
|
46
|
+
|
|
47
|
+
if (ev && ev.args) {
|
|
48
|
+
// event signature: PurchasedWithETH(address indexed user, uint256 ethIn, uint256 shares, uint256 tokenId)
|
|
49
|
+
const { user, ethIn, shares, tokenId } = ev.args as any;
|
|
50
|
+
|
|
51
|
+
purchased = {
|
|
52
|
+
buyer: user,
|
|
53
|
+
amount: BigNumber.from(ethIn),
|
|
54
|
+
shares: BigNumber.from(shares),
|
|
55
|
+
tokenId: BigNumber.from(tokenId),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
txHash: tx.hash,
|
|
61
|
+
receipt,
|
|
62
|
+
purchased,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Purchase warrants by transferring liqETH into the pool (ERC-20) and calling Depositor.purchaseWarrantsWithLiqETH(amountLiq, buyer).
|
|
68
|
+
* Returns txHash, receipt and parsed PurchasedWithLiqETH event (if present).
|
|
69
|
+
*/
|
|
70
|
+
async purchaseWarrantsWithLiqETH(amountLiq: BigNumber, buyer: string): Promise<any> {
|
|
71
|
+
// attempt a simulation of the purchase call
|
|
72
|
+
try {
|
|
73
|
+
await this.contract.Depositor.callStatic.purchaseWarrantsWithLiqETH(amountLiq, buyer);
|
|
74
|
+
} catch (err: any) {
|
|
75
|
+
let errorObj = formatContractErrors(err);
|
|
76
|
+
|
|
77
|
+
// ! TEMP for testing
|
|
78
|
+
if(errorObj.name == "OPP_PreviousEpochUnsent") {
|
|
79
|
+
console.error("OPP Previous Epoch is unsent - trigger OPP finalizeEpoch()")
|
|
80
|
+
await sendOPPFinalize(this.contract.OPP);
|
|
81
|
+
throw new Error(errorObj.name+` - triggering OPP finalizeEpoch() please try again`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
throw new Error(errorObj.name ?? errorObj.raw)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// attempt the real purchase call
|
|
88
|
+
let tx, receipt;
|
|
89
|
+
try {
|
|
90
|
+
tx = await this.contract.Depositor.purchaseWarrantsWithLiqETH(amountLiq, buyer);
|
|
91
|
+
receipt = await tx.wait(1);
|
|
92
|
+
} catch (err: any) {
|
|
93
|
+
let errorObj = formatContractErrors(err);
|
|
94
|
+
throw new Error(errorObj.name ?? errorObj.raw)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
// Attempt to parse PurchasedWithLiqETH event
|
|
99
|
+
let purchased: any | undefined;
|
|
100
|
+
const ev = receipt.events?.find((e) => e.event === 'PurchasedWithLiqETH' || (e.event && e.event.toString().startsWith('PurchasedWithLiqETH')));
|
|
101
|
+
|
|
102
|
+
if (ev && ev.args) {
|
|
103
|
+
// Event shape: PurchasedWithLiqETH(buyer, amountLiq, ethEqWei, shares, tokenId)
|
|
104
|
+
const args: any = ev.args;
|
|
105
|
+
// try named fields first, fallback to positional
|
|
106
|
+
const evtBuyer = args.buyer ?? args[0];
|
|
107
|
+
const evtAmountLiq = (args.amountLiq ?? args[1]) ? BigNumber.from(args.amountLiq ?? args[1]) : undefined;
|
|
108
|
+
const evtEthEqWei = (args.ethEqWei ?? args[2]) ? BigNumber.from(args.ethEqWei ?? args[2]) : undefined;
|
|
109
|
+
const evtShares = (args.shares ?? args[3]) ? BigNumber.from(args.shares ?? args[3]) : undefined;
|
|
110
|
+
const evtTokenId = (args.tokenId ?? args[4]) ? BigNumber.from(args.tokenId ?? args[4]) : undefined;
|
|
111
|
+
|
|
112
|
+
purchased = {
|
|
113
|
+
buyer: evtBuyer,
|
|
114
|
+
amountLiq: evtAmountLiq,
|
|
115
|
+
ethEqWei: evtEthEqWei,
|
|
116
|
+
shares: evtShares,
|
|
117
|
+
tokenId: evtTokenId,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return {
|
|
122
|
+
txHash: tx.hash,
|
|
123
|
+
receipt,
|
|
124
|
+
purchased,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { BigNumber, ethers } from "ethers";
|
|
2
|
-
import { preLaunchReceipt, StakedEvent,
|
|
2
|
+
import { preLaunchReceipt, StakedEvent, WithdrawnStakeEvent, WithdrawnStakeResult } from "../types";
|
|
3
3
|
import { EthereumContractService } from "../contract";
|
|
4
|
+
import { formatContractErrors } from "../utils";
|
|
4
5
|
|
|
5
6
|
export class StakeClient {
|
|
6
7
|
|
|
@@ -15,19 +16,72 @@ export class StakeClient {
|
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
|
-
* Simulate a stake via callStatic
|
|
19
|
-
*
|
|
20
|
-
* Useful for pre-flight checks; will throw with the same revert
|
|
21
|
-
* reason as a real tx if it would fail.
|
|
19
|
+
* Simulate a stake via callStatic
|
|
22
20
|
*/
|
|
23
|
-
async simulateStake(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
21
|
+
async simulateStake(amountWei: BigNumber): Promise<void> {
|
|
22
|
+
try {
|
|
23
|
+
await this.contract.Depositor.callStatic.stakeLiqETH(amountWei);
|
|
24
|
+
} catch (err: any) {
|
|
25
|
+
let errorObj = formatContractErrors(err);
|
|
26
|
+
throw new Error(errorObj.name ?? errorObj.raw)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Read OPP / Outpost state used by the Depositor to decide whether staking is allowed.
|
|
33
|
+
* Returns various data
|
|
34
|
+
*/
|
|
35
|
+
async getOppStatus(): Promise<any> {
|
|
36
|
+
const depositor = this.contract.Depositor;
|
|
37
|
+
const opp = this.contract.OPP;
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
const oppAddress: string = await depositor.oppAddress();
|
|
41
|
+
const oppInboundAddress: string = await depositor.oppInboundAddress();
|
|
42
|
+
const prevEpochSent = await opp.prevEpochSent();
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
const inbound = this.contractService.getReadOnly('OPPInbound');
|
|
46
|
+
|
|
47
|
+
// Query useful getters
|
|
48
|
+
const nextEpochBN: any = await inbound.nextEpochNum();
|
|
49
|
+
const pendingEpochRaw: any = await inbound.pendingEpoch();
|
|
50
|
+
const pendingMessageCount: any = await inbound.pendingMessageCount();
|
|
51
|
+
const previousEpochHash: string = await inbound.previousEpochHash();
|
|
52
|
+
const nextEpochNum = (nextEpochBN && typeof nextEpochBN.toNumber === 'function') ? nextEpochBN.toNumber() : Number(nextEpochBN || 0);
|
|
53
|
+
|
|
54
|
+
const pendingEpoch = (pendingEpochRaw && pendingEpochRaw.epochNumber !== undefined)
|
|
55
|
+
? {
|
|
56
|
+
epochNumber: (pendingEpochRaw.epochNumber && typeof pendingEpochRaw.epochNumber.toNumber === 'function') ? pendingEpochRaw.epochNumber.toNumber() : Number(pendingEpochRaw.epochNumber || 0),
|
|
57
|
+
timestamp: (pendingEpochRaw.timestamp && typeof pendingEpochRaw.timestamp.toNumber === 'function') ? pendingEpochRaw.timestamp.toNumber() : Number(pendingEpochRaw.timestamp || 0),
|
|
58
|
+
prevEpochHash: pendingEpochRaw.prevEpochHash,
|
|
59
|
+
merkleRoot: pendingEpochRaw.merkleRoot,
|
|
60
|
+
firstMessageID: pendingEpochRaw.firstMessageID,
|
|
61
|
+
lastMessageID: pendingEpochRaw.lastMessageID,
|
|
62
|
+
}
|
|
63
|
+
: null;
|
|
64
|
+
|
|
65
|
+
const pendingMessagesBN = pendingMessageCount;
|
|
66
|
+
const pendingMessages = (pendingMessagesBN && typeof pendingMessagesBN.toString === 'function') ? pendingMessagesBN.toString() : String(pendingMessagesBN || '0');
|
|
67
|
+
|
|
68
|
+
const hasPendingMessages = (pendingMessagesBN && typeof pendingMessagesBN.gt === 'function') ? pendingMessagesBN.gt(0) : (Number(pendingMessages) > 0);
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
oppAddress,
|
|
72
|
+
prevEpochSent,
|
|
73
|
+
oppInboundAddress,
|
|
74
|
+
nextEpochNum,
|
|
75
|
+
pendingEpoch,
|
|
76
|
+
pendingMessageCount: pendingMessages,
|
|
77
|
+
previousEpochHash,
|
|
78
|
+
hasPendingMessages,
|
|
79
|
+
raw: {
|
|
80
|
+
nextEpochBN,
|
|
81
|
+
pendingEpochRaw,
|
|
82
|
+
pendingMessageCount: pendingMessagesBN,
|
|
83
|
+
},
|
|
84
|
+
};
|
|
31
85
|
}
|
|
32
86
|
|
|
33
87
|
|
|
@@ -36,12 +90,17 @@ export class StakeClient {
|
|
|
36
90
|
* @param amountWei an amount of liqETH (in WEI) to stake to the Outpost
|
|
37
91
|
* @returns txHash (hash of the transaction), receipt, Staked event
|
|
38
92
|
*/
|
|
39
|
-
async performStake(amountWei: BigNumber, signerAddress: string): Promise<
|
|
40
|
-
const
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
93
|
+
async performStake(amountWei: BigNumber, signerAddress: string): Promise<any> {
|
|
94
|
+
const depositor = this.contract.Depositor.address;
|
|
95
|
+
const liqRead = this.contract.LiqEth;
|
|
96
|
+
const bal = await liqRead.balanceOf(signerAddress);
|
|
97
|
+
const allowance = await liqRead.allowance(signerAddress, depositor);
|
|
98
|
+
|
|
99
|
+
const paused = await this.contract.Depositor.paused();
|
|
100
|
+
if(paused) {
|
|
101
|
+
throw new Error("Error - Depositor is in a paused state");
|
|
102
|
+
}
|
|
103
|
+
|
|
45
104
|
|
|
46
105
|
// if allowance is less than the requested stake amount, request permission to spend LiqEth
|
|
47
106
|
if (allowance.lt(amountWei)) {
|
|
@@ -50,17 +109,20 @@ export class StakeClient {
|
|
|
50
109
|
// currently requested unlimited amount - potentially change to only request up to the current amount?
|
|
51
110
|
const approveAmount = ethers.constants.MaxUint256;
|
|
52
111
|
|
|
53
|
-
console.warn(`allowance insufficient (${allowance.toString()} < ${amountWei.toString()}); sending approve(${
|
|
54
|
-
const approveTx = await liqWrite.approve(
|
|
112
|
+
console.warn(`allowance insufficient (${allowance.toString()} < ${amountWei.toString()}); sending approve(${depositor}, ${approveAmount.toString()})`);
|
|
113
|
+
const approveTx = await liqWrite.approve(depositor, approveAmount);
|
|
55
114
|
await approveTx.wait(1);
|
|
56
115
|
|
|
57
116
|
// re-read allowance to ensure approval succeeded
|
|
58
|
-
const newAllowance = await
|
|
117
|
+
const newAllowance = await liqRead.allowance(signerAddress, depositor);
|
|
59
118
|
if (newAllowance.lt(amountWei)) {
|
|
60
119
|
throw new Error('Approval failed or allowance still insufficient after approve');
|
|
61
120
|
}
|
|
62
121
|
}
|
|
63
122
|
|
|
123
|
+
|
|
124
|
+
await this.simulateStake(amountWei);
|
|
125
|
+
|
|
64
126
|
|
|
65
127
|
// send the tx to stake liqeth
|
|
66
128
|
const tx = await this.contract.Depositor.stakeLiqETH(amountWei);
|
|
@@ -150,7 +212,6 @@ export class StakeClient {
|
|
|
150
212
|
for (const idBN of tokenIds) {
|
|
151
213
|
try {
|
|
152
214
|
const receiptData = await receiptContract.getReceipt(idBN);
|
|
153
|
-
|
|
154
215
|
const formattedReceipt = {
|
|
155
216
|
account: receiptData.account,
|
|
156
217
|
currency: receiptData.currency,
|
|
@@ -169,7 +230,8 @@ export class StakeClient {
|
|
|
169
230
|
timestamp: new Date(Number(receiptData.timestamp.toString()) * 1000).toLocaleString(),
|
|
170
231
|
}
|
|
171
232
|
|
|
172
|
-
|
|
233
|
+
// Only fetch staking receipts (kind 1 is a wire pretoken receipt)
|
|
234
|
+
if(receiptData.kind == 0) results.push({ tokenId: idBN.toBigInt(), receipt: formattedReceipt } as any);
|
|
173
235
|
} catch (err) {
|
|
174
236
|
// in case of any mismatch or race, just skip this id
|
|
175
237
|
console.warn(`Failed to load receipt for tokenId=${idBN.toString()}`, err);
|
|
@@ -177,6 +239,7 @@ export class StakeClient {
|
|
|
177
239
|
}
|
|
178
240
|
}
|
|
179
241
|
|
|
242
|
+
console.log('results of prelaunch receipts', results)
|
|
180
243
|
return results;
|
|
181
244
|
}
|
|
182
245
|
|
|
@@ -21,6 +21,8 @@ import OPPArtifact from '../../assets/ethereum/ABI/outpost/OPP.sol/OPP.json';
|
|
|
21
21
|
import OPPCommonArtifact from '../../assets/ethereum/ABI/outpost/OPPCommon.sol/OPPCommon.json';
|
|
22
22
|
import OPPInboundArtifact from '../../assets/ethereum/ABI/outpost/OPPInbound.sol/OPPInbound.json';
|
|
23
23
|
import WarrantArtifact from '../../assets/ethereum/ABI/outpost/Warrant.sol/Warrant.json';
|
|
24
|
+
import AggregatorArtifact from '../../assets/ethereum/ABI/outpost/Aggregator.sol/Aggregator.json';
|
|
25
|
+
import EthUsdPriceConsumerArtifact from '../../assets/ethereum/ABI/outpost/EthUsdPriceConsumer.sol/EthUsdPriceConsumer.json';
|
|
24
26
|
|
|
25
27
|
// Currently Unused Artifacts
|
|
26
28
|
// import LiqEthCommonArtifact from '../../assets/ethereum/ABI/liqEth/liqEthCommon.sol/liqEthCommon.json';
|
|
@@ -64,6 +66,9 @@ export const ADDRESSES: AddressBook = {
|
|
|
64
66
|
OPPCommon: "0x52C1d7F02B35176F79b03F6eF7E5b74b27d1dB8c",
|
|
65
67
|
OPPInbound: "0x39feC7536BaEd4E376b1B5cf2f2e8182ab203418",
|
|
66
68
|
Warrant: "0x9190bBcaB5cfeb4b7b6DE5Ae21105F3114753F10",
|
|
69
|
+
|
|
70
|
+
Aggregator: "0xd89F85Ce867E523Dc3E58578B06Ee72cdaBc39ec",
|
|
71
|
+
EthUsdPriceConsumer: "0xd02F512eAcCA4c713CA954DfD907DC6E8cFACf8e",
|
|
67
72
|
};
|
|
68
73
|
|
|
69
74
|
export type Contracts<T extends string = ContractName> = Record<T, ContractConfig>;
|
|
@@ -156,6 +161,14 @@ export const CONTRACTS: Contracts<ContractName> = {
|
|
|
156
161
|
Warrant: {
|
|
157
162
|
address: ADDRESSES.Warrant,
|
|
158
163
|
abi: WarrantArtifact.abi as JsonFragment[],
|
|
164
|
+
},
|
|
165
|
+
Aggregator: {
|
|
166
|
+
address: ADDRESSES.Aggregator,
|
|
167
|
+
abi: AggregatorArtifact.abi as JsonFragment[],
|
|
168
|
+
},
|
|
169
|
+
EthUsdPriceConsumer: {
|
|
170
|
+
address: ADDRESSES.EthUsdPriceConsumer,
|
|
171
|
+
abi: EthUsdPriceConsumerArtifact.abi as JsonFragment[],
|
|
159
172
|
}
|
|
160
173
|
};
|
|
161
174
|
|