@haven-fi/solauto-sdk 1.0.837 → 1.0.838
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/README.md +4 -0
- package/dist/services/transactions/manager/clientTransactionsManager.d.ts +10 -1
- package/dist/services/transactions/manager/clientTransactionsManager.d.ts.map +1 -1
- package/dist/services/transactions/manager/clientTransactionsManager.js +7 -1
- package/package.json +1 -1
- package/src/services/transactions/manager/clientTransactionsManager.ts +23 -2
- package/tests/unit/clientTransactionsManager.ts +140 -0
package/README.md
CHANGED
|
@@ -75,6 +75,10 @@ const statuses = txManager.send(transactionItems);
|
|
|
75
75
|
|
|
76
76
|
## Rebalancing an existing position
|
|
77
77
|
|
|
78
|
+
For automated rebalancers, set `autoUpdateLookupTable: false` on
|
|
79
|
+
`ClientTransactionsManager` to skip creating or extending the authority lookup
|
|
80
|
+
table. Existing lookup tables are still used. The option defaults to `true`.
|
|
81
|
+
|
|
78
82
|
```typescript
|
|
79
83
|
import * as solauto from "@haven-fi/solauto-sdk";
|
|
80
84
|
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
import { SolautoClient } from "../../solauto";
|
|
2
|
-
import { TransactionsManager } from "./transactionsManager";
|
|
2
|
+
import { TransactionsManager, TransactionsManagerArgs } from "./transactionsManager";
|
|
3
3
|
import { TransactionItem } from "../types";
|
|
4
|
+
export interface ClientTransactionsManagerArgs extends TransactionsManagerArgs<SolautoClient> {
|
|
5
|
+
/**
|
|
6
|
+
* Create or extend the authority lookup table before sending. Defaults to true.
|
|
7
|
+
* Existing lookup tables are still used when false.
|
|
8
|
+
*/
|
|
9
|
+
autoUpdateLookupTable?: boolean;
|
|
10
|
+
}
|
|
4
11
|
export declare class ClientTransactionsManager extends TransactionsManager<SolautoClient> {
|
|
12
|
+
private readonly autoUpdateLookupTable;
|
|
13
|
+
constructor(args: ClientTransactionsManagerArgs);
|
|
5
14
|
private updateLut;
|
|
6
15
|
private addChoreTxs;
|
|
7
16
|
send(transactions: TransactionItem[]): Promise<import("./transactionsManager").TransactionManagerStatuses>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clientTransactionsManager.d.ts","sourceRoot":"","sources":["../../../../src/services/transactions/manager/clientTransactionsManager.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,
|
|
1
|
+
{"version":3,"file":"clientTransactionsManager.d.ts","sourceRoot":"","sources":["../../../../src/services/transactions/manager/clientTransactionsManager.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EACL,mBAAmB,EACnB,uBAAuB,EACxB,MAAM,uBAAuB,CAAC;AAI/B,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAI3C,MAAM,WAAW,6BACf,SAAQ,uBAAuB,CAAC,aAAa,CAAC;IAC9C;;;OAGG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,qBAAa,yBAA0B,SAAQ,mBAAmB,CAAC,aAAa,CAAC;IAC/E,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAU;gBAEpC,IAAI,EAAE,6BAA6B;YAKjC,SAAS;YAmBT,WAAW;IA4CZ,IAAI,CAAC,YAAY,EAAE,eAAe,EAAE;CAqClD"}
|
|
@@ -8,6 +8,10 @@ const types_1 = require("../types");
|
|
|
8
8
|
const transactionUtils_1 = require("../transactionUtils");
|
|
9
9
|
const constants_1 = require("../../../constants");
|
|
10
10
|
class ClientTransactionsManager extends transactionsManager_1.TransactionsManager {
|
|
11
|
+
constructor(args) {
|
|
12
|
+
super(args);
|
|
13
|
+
this.autoUpdateLookupTable = args.autoUpdateLookupTable ?? true;
|
|
14
|
+
}
|
|
11
15
|
async updateLut(tx, newLut) {
|
|
12
16
|
const lutInputs = await this.lookupTables.getLutInputs();
|
|
13
17
|
const updateLutTxName = `${newLut ? "create" : "update"} lookup table`;
|
|
@@ -37,7 +41,9 @@ class ClientTransactionsManager extends transactionsManager_1.TransactionsManage
|
|
|
37
41
|
async send(transactions) {
|
|
38
42
|
const items = [...transactions];
|
|
39
43
|
const client = this.txHandler;
|
|
40
|
-
const updateLut =
|
|
44
|
+
const updateLut = this.autoUpdateLookupTable
|
|
45
|
+
? await client.updateLookupTable()
|
|
46
|
+
: undefined;
|
|
41
47
|
const updateLutInSepTx = updateLut?.new || (updateLut?.accountsToAdd ?? []).length > 4;
|
|
42
48
|
if (updateLut && updateLutInSepTx) {
|
|
43
49
|
await this.updateLut(updateLut.tx, updateLut.new);
|
package/package.json
CHANGED
|
@@ -3,7 +3,10 @@ import {
|
|
|
3
3
|
TransactionBuilder,
|
|
4
4
|
} from "@metaplex-foundation/umi";
|
|
5
5
|
import { SolautoClient } from "../../solauto";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
TransactionsManager,
|
|
8
|
+
TransactionsManagerArgs,
|
|
9
|
+
} from "./transactionsManager";
|
|
7
10
|
import {
|
|
8
11
|
retryWithExponentialBackoff,
|
|
9
12
|
} from "../../../utils";
|
|
@@ -11,7 +14,23 @@ import { TransactionItem } from "../types";
|
|
|
11
14
|
import { getTransactionChores } from "../transactionUtils";
|
|
12
15
|
import { CHORES_TX_NAME } from "../../../constants";
|
|
13
16
|
|
|
17
|
+
export interface ClientTransactionsManagerArgs
|
|
18
|
+
extends TransactionsManagerArgs<SolautoClient> {
|
|
19
|
+
/**
|
|
20
|
+
* Create or extend the authority lookup table before sending. Defaults to true.
|
|
21
|
+
* Existing lookup tables are still used when false.
|
|
22
|
+
*/
|
|
23
|
+
autoUpdateLookupTable?: boolean;
|
|
24
|
+
}
|
|
25
|
+
|
|
14
26
|
export class ClientTransactionsManager extends TransactionsManager<SolautoClient> {
|
|
27
|
+
private readonly autoUpdateLookupTable: boolean;
|
|
28
|
+
|
|
29
|
+
constructor(args: ClientTransactionsManagerArgs) {
|
|
30
|
+
super(args);
|
|
31
|
+
this.autoUpdateLookupTable = args.autoUpdateLookupTable ?? true;
|
|
32
|
+
}
|
|
33
|
+
|
|
15
34
|
private async updateLut(tx: TransactionBuilder, newLut: boolean) {
|
|
16
35
|
const lutInputs = await this.lookupTables.getLutInputs();
|
|
17
36
|
const updateLutTxName = `${newLut ? "create" : "update"} lookup table`;
|
|
@@ -79,7 +98,9 @@ export class ClientTransactionsManager extends TransactionsManager<SolautoClient
|
|
|
79
98
|
const items = [...transactions];
|
|
80
99
|
const client = this.txHandler as SolautoClient;
|
|
81
100
|
|
|
82
|
-
const updateLut =
|
|
101
|
+
const updateLut = this.autoUpdateLookupTable
|
|
102
|
+
? await client.updateLookupTable()
|
|
103
|
+
: undefined;
|
|
83
104
|
|
|
84
105
|
const updateLutInSepTx =
|
|
85
106
|
updateLut?.new || (updateLut?.accountsToAdd ?? []).length > 4;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { expect } from "chai";
|
|
2
|
+
import { afterEach, beforeEach, describe, it } from "mocha";
|
|
3
|
+
import {
|
|
4
|
+
publicKey,
|
|
5
|
+
transactionBuilder,
|
|
6
|
+
TransactionBuilder,
|
|
7
|
+
} from "@metaplex-foundation/umi";
|
|
8
|
+
import { AddressLookupTableProgram, PublicKey } from "@solana/web3.js";
|
|
9
|
+
import {
|
|
10
|
+
ClientTransactionsManager,
|
|
11
|
+
SolautoClient,
|
|
12
|
+
TransactionItem,
|
|
13
|
+
TransactionsManager,
|
|
14
|
+
} from "../../src";
|
|
15
|
+
import * as transactionUtils from "../../src/services/transactions/transactionUtils";
|
|
16
|
+
|
|
17
|
+
describe("ClientTransactionsManager lookup table updates", () => {
|
|
18
|
+
const originalSend = TransactionsManager.prototype.send;
|
|
19
|
+
const originalChores = transactionUtils.getTransactionChores;
|
|
20
|
+
let submittedItems: TransactionItem[];
|
|
21
|
+
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
submittedItems = [];
|
|
24
|
+
TransactionsManager.prototype.send = async (items) => {
|
|
25
|
+
submittedItems = items;
|
|
26
|
+
return [];
|
|
27
|
+
};
|
|
28
|
+
(transactionUtils as any).getTransactionChores = async () => [
|
|
29
|
+
transactionBuilder(),
|
|
30
|
+
transactionBuilder(),
|
|
31
|
+
];
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
afterEach(() => {
|
|
35
|
+
TransactionsManager.prototype.send = originalSend;
|
|
36
|
+
(transactionUtils as any).getTransactionChores = originalChores;
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
function createManager(
|
|
40
|
+
updateLookupTable: SolautoClient["updateLookupTable"],
|
|
41
|
+
autoUpdateLookupTable?: boolean
|
|
42
|
+
) {
|
|
43
|
+
let resets = 0;
|
|
44
|
+
const client = {
|
|
45
|
+
defaultLookupTables: () => ["existing-authority-table"],
|
|
46
|
+
updateLookupTable,
|
|
47
|
+
resetLiveTxUpdates: async () => {
|
|
48
|
+
resets++;
|
|
49
|
+
},
|
|
50
|
+
log: () => {},
|
|
51
|
+
umi: {},
|
|
52
|
+
} as unknown as SolautoClient;
|
|
53
|
+
const manager = new ClientTransactionsManager({
|
|
54
|
+
txHandler: client,
|
|
55
|
+
autoUpdateLookupTable,
|
|
56
|
+
});
|
|
57
|
+
const separateUpdates: TransactionBuilder[] = [];
|
|
58
|
+
(manager as any).updateLut = async (tx: TransactionBuilder) => {
|
|
59
|
+
separateUpdates.push(tx);
|
|
60
|
+
};
|
|
61
|
+
return { manager, separateUpdates, resets: () => resets };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
it("skips lookup table writes while keeping existing tables and processing transactions", async () => {
|
|
65
|
+
const { manager, separateUpdates, resets } = createManager(
|
|
66
|
+
async () => {
|
|
67
|
+
throw new Error("A full lookup table must never be extended");
|
|
68
|
+
},
|
|
69
|
+
false
|
|
70
|
+
);
|
|
71
|
+
const item = new TransactionItem(
|
|
72
|
+
async () => ({ tx: transactionBuilder() }),
|
|
73
|
+
"rebalance"
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
await manager.send([item]);
|
|
77
|
+
|
|
78
|
+
expect(item.initialized).to.equal(true);
|
|
79
|
+
expect(submittedItems).to.deep.equal([item]);
|
|
80
|
+
expect(separateUpdates).to.deep.equal([]);
|
|
81
|
+
expect((manager as any).lookupTables.defaultLuts).to.deep.equal([
|
|
82
|
+
"existing-authority-table",
|
|
83
|
+
]);
|
|
84
|
+
expect(resets()).to.equal(1);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
for (const scenario of [
|
|
88
|
+
{
|
|
89
|
+
name: "a small extension in the chores transaction",
|
|
90
|
+
new: false,
|
|
91
|
+
count: 1,
|
|
92
|
+
separate: false,
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
name: "a large extension separately",
|
|
96
|
+
new: false,
|
|
97
|
+
count: 5,
|
|
98
|
+
separate: true,
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
name: "a new lookup table separately",
|
|
102
|
+
new: true,
|
|
103
|
+
count: 1,
|
|
104
|
+
separate: true,
|
|
105
|
+
},
|
|
106
|
+
]) {
|
|
107
|
+
it(`still sends ${scenario.name} by default`, async () => {
|
|
108
|
+
const updateTx = transactionBuilder().add({
|
|
109
|
+
instruction: {
|
|
110
|
+
programId: publicKey(AddressLookupTableProgram.programId.toBase58()),
|
|
111
|
+
keys: [],
|
|
112
|
+
data: new Uint8Array([2, 0, 0, 0]),
|
|
113
|
+
},
|
|
114
|
+
signers: [],
|
|
115
|
+
bytesCreatedOnChain: 0,
|
|
116
|
+
});
|
|
117
|
+
let updateCalls = 0;
|
|
118
|
+
const { manager, separateUpdates } = createManager(async () => {
|
|
119
|
+
updateCalls++;
|
|
120
|
+
return {
|
|
121
|
+
tx: updateTx,
|
|
122
|
+
new: scenario.new,
|
|
123
|
+
accountsToAdd: Array(scenario.count).fill(PublicKey.default),
|
|
124
|
+
};
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
await manager.send([]);
|
|
128
|
+
|
|
129
|
+
expect(updateCalls).to.equal(1);
|
|
130
|
+
expect(separateUpdates).to.deep.equal(
|
|
131
|
+
scenario.separate ? [updateTx] : []
|
|
132
|
+
);
|
|
133
|
+
expect(
|
|
134
|
+
submittedItems.flatMap((item) => item.tx!.getInstructions())
|
|
135
|
+
).to.deep.equal(
|
|
136
|
+
scenario.separate ? [] : updateTx.getInstructions()
|
|
137
|
+
);
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
});
|