@flashbacktech/flashbackclient 0.0.13
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/LICENSE +21 -0
- package/README.md +35 -0
- package/dist/stellar/client.d.ts +282 -0
- package/dist/stellar/client.js +450 -0
- package/dist/stellar/consumer.d.ts +10 -0
- package/dist/stellar/consumer.js +77 -0
- package/dist/stellar/decorator.d.ts +1 -0
- package/dist/stellar/decorator.js +30 -0
- package/dist/stellar/index.d.ts +4 -0
- package/dist/stellar/index.js +2 -0
- package/dist/stellar/models.d.ts +55 -0
- package/dist/stellar/models.js +1 -0
- package/dist/stellar/provider.d.ts +10 -0
- package/dist/stellar/provider.js +77 -0
- package/dist/stellar/reservation.d.ts +8 -0
- package/dist/stellar/reservation.js +54 -0
- package/dist/stellar/stats.d.ts +4 -0
- package/dist/stellar/stats.js +9 -0
- package/dist/stellar/transaction.d.ts +24 -0
- package/dist/stellar/transaction.js +130 -0
- package/dist/stellar/unit.d.ts +12 -0
- package/dist/stellar/unit.js +90 -0
- package/dist/utils/timing.d.ts +1 -0
- package/dist/utils/timing.js +15 -0
- package/package.json +81 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { prepareTransaction, sendTransaction } from './transaction.js';
|
|
2
|
+
const get_provider = async (context, wallet_address, provider_address, load_units = false) => {
|
|
3
|
+
const [provider, units] = await Promise.all([
|
|
4
|
+
prepareTransaction(context, wallet_address, {
|
|
5
|
+
method: 'get_provider',
|
|
6
|
+
args: [{ value: provider_address, type: 'address' }],
|
|
7
|
+
}),
|
|
8
|
+
load_units
|
|
9
|
+
? get_provider_units(context, wallet_address, provider_address)
|
|
10
|
+
: new Map(),
|
|
11
|
+
]);
|
|
12
|
+
const typedProviderData = provider.isSuccess ? provider.result : null;
|
|
13
|
+
if (typedProviderData) {
|
|
14
|
+
typedProviderData.units = units;
|
|
15
|
+
}
|
|
16
|
+
return typedProviderData;
|
|
17
|
+
};
|
|
18
|
+
const get_provider_units = async (context, wallet_address, provider_address) => {
|
|
19
|
+
const response = await prepareTransaction(context, wallet_address, {
|
|
20
|
+
method: 'get_provider_units',
|
|
21
|
+
args: [{ value: provider_address, type: 'address' }],
|
|
22
|
+
});
|
|
23
|
+
const typedProviderUnits = response.isSuccess
|
|
24
|
+
? response.result
|
|
25
|
+
: new Map();
|
|
26
|
+
return typedProviderUnits;
|
|
27
|
+
};
|
|
28
|
+
const get_providers = async (context, wallet_address, skip = 0, take = 10) => {
|
|
29
|
+
const response = await prepareTransaction(context, wallet_address, {
|
|
30
|
+
method: 'get_providers',
|
|
31
|
+
args: [
|
|
32
|
+
{ value: skip, type: 'u32' },
|
|
33
|
+
{ value: take, type: 'u32' },
|
|
34
|
+
],
|
|
35
|
+
});
|
|
36
|
+
if (!response.isSuccess) {
|
|
37
|
+
return new Map();
|
|
38
|
+
}
|
|
39
|
+
const providersObj = response.result;
|
|
40
|
+
return new Map(Object.entries(providersObj));
|
|
41
|
+
};
|
|
42
|
+
const get_provider_count = async (context, wallet_address) => {
|
|
43
|
+
const response = await prepareTransaction(context, wallet_address, {
|
|
44
|
+
method: 'get_provider_count',
|
|
45
|
+
});
|
|
46
|
+
return response.isSuccess ? response.result : 0;
|
|
47
|
+
};
|
|
48
|
+
// Helper function to handle write-mode contract calls
|
|
49
|
+
const executeProviderTransaction = async (context, wallet_address, provider_address, method, additionalArgs = []) => {
|
|
50
|
+
const isOwner = wallet_address !== provider_address;
|
|
51
|
+
const response = await prepareTransaction(context, wallet_address, {
|
|
52
|
+
method,
|
|
53
|
+
args: [
|
|
54
|
+
{ value: provider_address, type: 'address' },
|
|
55
|
+
...additionalArgs,
|
|
56
|
+
{ value: isOwner, type: 'bool' },
|
|
57
|
+
],
|
|
58
|
+
});
|
|
59
|
+
if (response.isSuccess && !response.isReadOnly) {
|
|
60
|
+
const signedTxXDR = await context.signTransaction(response.result);
|
|
61
|
+
await sendTransaction(context, signedTxXDR);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
const register_provider = async (context, wallet_address, provider_address, provider_description) => {
|
|
65
|
+
await executeProviderTransaction(context, wallet_address, provider_address, 'register_provider', [
|
|
66
|
+
{ value: provider_description, type: 'string' },
|
|
67
|
+
]);
|
|
68
|
+
};
|
|
69
|
+
const delete_provider = async (context, wallet_address, provider_address) => {
|
|
70
|
+
await executeProviderTransaction(context, wallet_address, provider_address, 'delete_provider');
|
|
71
|
+
};
|
|
72
|
+
const update_provider = async (context, wallet_address, provider_address, provider_description) => {
|
|
73
|
+
await executeProviderTransaction(context, wallet_address, provider_address, 'update_provider', [
|
|
74
|
+
{ value: provider_description, type: 'string' },
|
|
75
|
+
]);
|
|
76
|
+
};
|
|
77
|
+
export { get_provider, get_provider_units, get_providers, get_provider_count, register_provider, delete_provider, update_provider, };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ClientContext } from './client.js';
|
|
2
|
+
import { DeletionStatus, StorageReservation } from './models.js';
|
|
3
|
+
declare const get_reservation: (context: ClientContext, wallet_address: string, reservation_id: number) => Promise<StorageReservation | null>;
|
|
4
|
+
declare const create_reservation: (context: ClientContext, wallet_address: string, consumer_address: string, unit_id: number, reserved_gb: number) => Promise<boolean>;
|
|
5
|
+
declare const delete_reservation: (context: ClientContext, wallet_address: string, consumer_address: string, reservation_id: number) => Promise<DeletionStatus>;
|
|
6
|
+
declare const update_inuse_bytes_consumer: (context: ClientContext, wallet_address: string, consumer_address: string, reservation_id: number, inuse_bytes: number) => Promise<boolean>;
|
|
7
|
+
declare const update_inuse_bytes_provider: (context: ClientContext, wallet_address: string, provider_address: string, reservation_id: number, inuse_bytes: number) => Promise<boolean>;
|
|
8
|
+
export { get_reservation, create_reservation, delete_reservation, update_inuse_bytes_consumer, update_inuse_bytes_provider, };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { prepareTransaction, sendTransaction } from './transaction.js';
|
|
2
|
+
const get_reservation = async (context, wallet_address, reservation_id) => {
|
|
3
|
+
const response = await prepareTransaction(context, wallet_address, {
|
|
4
|
+
method: 'get_reservation',
|
|
5
|
+
args: [{ value: reservation_id, type: 'u32' }],
|
|
6
|
+
});
|
|
7
|
+
return response.isSuccess ? response.result : null;
|
|
8
|
+
};
|
|
9
|
+
const executeReservationTransaction = async (context, wallet_address, method, additionalArgs = [], defaultValue) => {
|
|
10
|
+
const response = await prepareTransaction(context, wallet_address, {
|
|
11
|
+
method,
|
|
12
|
+
args: additionalArgs,
|
|
13
|
+
});
|
|
14
|
+
if (response.isSuccess && !response.isReadOnly) {
|
|
15
|
+
const signedTxXDR = await context.signTransaction(response.result);
|
|
16
|
+
return sendTransaction(context, signedTxXDR);
|
|
17
|
+
}
|
|
18
|
+
return defaultValue;
|
|
19
|
+
};
|
|
20
|
+
const create_reservation = async (context, wallet_address, consumer_address, unit_id, reserved_gb) => {
|
|
21
|
+
const isOwner = wallet_address !== consumer_address;
|
|
22
|
+
return executeReservationTransaction(context, wallet_address, 'create_reservation', [
|
|
23
|
+
{ value: consumer_address, type: 'address' },
|
|
24
|
+
{ value: unit_id, type: 'u32' },
|
|
25
|
+
{ value: reserved_gb, type: 'u64' },
|
|
26
|
+
{ value: isOwner, type: 'bool' },
|
|
27
|
+
]);
|
|
28
|
+
};
|
|
29
|
+
const delete_reservation = async (context, wallet_address, consumer_address, reservation_id) => {
|
|
30
|
+
const isOwner = wallet_address !== consumer_address;
|
|
31
|
+
return (executeReservationTransaction(context, wallet_address, 'delete_reservation', [
|
|
32
|
+
{ value: reservation_id, type: 'u32' },
|
|
33
|
+
{ value: isOwner, type: 'bool' },
|
|
34
|
+
]) || 'NotFound');
|
|
35
|
+
};
|
|
36
|
+
const update_inuse_bytes_consumer = async (context, wallet_address, consumer_address, reservation_id, inuse_bytes) => {
|
|
37
|
+
const isOwner = wallet_address !== consumer_address;
|
|
38
|
+
return executeReservationTransaction(context, wallet_address, 'update_inuse_bytes_consumer', [
|
|
39
|
+
{ value: reservation_id, type: 'u32' },
|
|
40
|
+
{ value: consumer_address, type: 'address' },
|
|
41
|
+
{ value: inuse_bytes, type: 'u64' },
|
|
42
|
+
{ value: isOwner, type: 'bool' },
|
|
43
|
+
]);
|
|
44
|
+
};
|
|
45
|
+
const update_inuse_bytes_provider = async (context, wallet_address, provider_address, reservation_id, inuse_bytes) => {
|
|
46
|
+
const isOwner = wallet_address !== provider_address;
|
|
47
|
+
return executeReservationTransaction(context, wallet_address, 'update_inuse_bytes_consumer', [
|
|
48
|
+
{ value: reservation_id, type: 'u32' },
|
|
49
|
+
{ value: provider_address, type: 'address' },
|
|
50
|
+
{ value: inuse_bytes, type: 'u64' },
|
|
51
|
+
{ value: isOwner, type: 'bool' },
|
|
52
|
+
]);
|
|
53
|
+
};
|
|
54
|
+
export { get_reservation, create_reservation, delete_reservation, update_inuse_bytes_consumer, update_inuse_bytes_provider, };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { prepareTransaction } from './transaction.js';
|
|
2
|
+
const get_stats = async (context, wallet_address) => {
|
|
3
|
+
const stats = await prepareTransaction(context, wallet_address, {
|
|
4
|
+
method: 'get_stats',
|
|
5
|
+
args: [],
|
|
6
|
+
});
|
|
7
|
+
return stats.isSuccess ? stats.result : null;
|
|
8
|
+
};
|
|
9
|
+
export { get_stats };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Transaction, Memo, MemoType, Operation, FeeBumpTransaction } from '@stellar/stellar-sdk';
|
|
2
|
+
import { ClientContext } from './client.js';
|
|
3
|
+
interface StellarNetwork {
|
|
4
|
+
network: string;
|
|
5
|
+
networkPassphrase: string;
|
|
6
|
+
}
|
|
7
|
+
declare const getNetwork: (network: string) => StellarNetwork;
|
|
8
|
+
declare const getPublicKeyFromPrivateKey: (privateKey: string) => string;
|
|
9
|
+
interface ContractMethodCall {
|
|
10
|
+
method: string;
|
|
11
|
+
args?: Array<{
|
|
12
|
+
value: number | string | bigint | boolean | null | undefined;
|
|
13
|
+
type: 'u32' | 'i32' | 'u64' | 'i64' | 'string' | 'symbol' | 'address' | 'bool';
|
|
14
|
+
}>;
|
|
15
|
+
}
|
|
16
|
+
interface ContractMethodResponse {
|
|
17
|
+
isSuccess: boolean;
|
|
18
|
+
isReadOnly: boolean;
|
|
19
|
+
result: string | unknown;
|
|
20
|
+
}
|
|
21
|
+
declare const prepareTransaction: (context: ClientContext, address: string, contractCall: ContractMethodCall) => Promise<ContractMethodResponse>;
|
|
22
|
+
declare const signTransaction: (context: ClientContext, xdrToSign: string, privateKey: string) => Promise<Transaction<Memo<MemoType>, Operation[]> | FeeBumpTransaction>;
|
|
23
|
+
declare const sendTransaction: (context: ClientContext, signedTransactionXDR: string) => Promise<any>;
|
|
24
|
+
export { prepareTransaction, sendTransaction, signTransaction, getNetwork, StellarNetwork, getPublicKeyFromPrivateKey, };
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { sleep } from '../utils/timing.js';
|
|
2
|
+
// Polyfill for BigInt JSON serialization
|
|
3
|
+
BigInt.prototype.toJSON = function () {
|
|
4
|
+
return this.toString();
|
|
5
|
+
};
|
|
6
|
+
import { Contract, TransactionBuilder, nativeToScVal, BASE_FEE, scValToNative, Keypair, } from '@stellar/stellar-sdk';
|
|
7
|
+
import { rpc } from '@stellar/stellar-sdk';
|
|
8
|
+
const getNetwork = (network) => {
|
|
9
|
+
let networkPassphrase = '';
|
|
10
|
+
switch (network) {
|
|
11
|
+
case 'TESTNET':
|
|
12
|
+
networkPassphrase = 'Test SDF Network ; September 2015';
|
|
13
|
+
break;
|
|
14
|
+
case 'PUBLIC':
|
|
15
|
+
networkPassphrase = 'Public Global Stellar Network ; September 2015';
|
|
16
|
+
break;
|
|
17
|
+
}
|
|
18
|
+
return { network, networkPassphrase };
|
|
19
|
+
};
|
|
20
|
+
const getPublicKeyFromPrivateKey = (privateKey) => {
|
|
21
|
+
const keypair = Keypair.fromSecret(privateKey);
|
|
22
|
+
return keypair.publicKey();
|
|
23
|
+
};
|
|
24
|
+
const getServer = (network) => {
|
|
25
|
+
let serverUrl = '';
|
|
26
|
+
switch (network.network) {
|
|
27
|
+
case 'TESTNET':
|
|
28
|
+
serverUrl = 'https://soroban-testnet.stellar.org:443';
|
|
29
|
+
break;
|
|
30
|
+
case 'PUBLIC':
|
|
31
|
+
serverUrl = 'https://rpc.stellar.org:443';
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
const server = new rpc.Server(serverUrl);
|
|
35
|
+
return server;
|
|
36
|
+
};
|
|
37
|
+
const TIMEOUT_TRANSACTION = 60;
|
|
38
|
+
const prepareTransaction = async (context, address, contractCall) => {
|
|
39
|
+
const contractAddress = context.contractAddress;
|
|
40
|
+
const contract = new Contract(contractAddress);
|
|
41
|
+
const server = getServer(context.network);
|
|
42
|
+
const sourceAccount = await server.getAccount(address);
|
|
43
|
+
const response = {
|
|
44
|
+
isSuccess: false,
|
|
45
|
+
isReadOnly: false,
|
|
46
|
+
result: '',
|
|
47
|
+
};
|
|
48
|
+
// Convert raw values to ScVal
|
|
49
|
+
const convertedArgs = contractCall.args?.map((arg) => nativeToScVal(arg.value, { type: arg.type })) || [];
|
|
50
|
+
const builtTransaction = new TransactionBuilder(sourceAccount, {
|
|
51
|
+
fee: BASE_FEE,
|
|
52
|
+
networkPassphrase: context.network.networkPassphrase,
|
|
53
|
+
})
|
|
54
|
+
.addOperation(contract.call(contractCall.method, ...convertedArgs))
|
|
55
|
+
.setTimeout(TIMEOUT_TRANSACTION)
|
|
56
|
+
.build();
|
|
57
|
+
const sim = await server.simulateTransaction(builtTransaction);
|
|
58
|
+
if (rpc.Api.isSimulationSuccess(sim)) {
|
|
59
|
+
response.isSuccess = true;
|
|
60
|
+
//console.log('Simulation success:', JSON.stringify(sim));
|
|
61
|
+
const result = sim.result && sim.result.retval ? scValToNative(sim.result.retval) : undefined;
|
|
62
|
+
const footprint = sim.transactionData.getFootprint();
|
|
63
|
+
const isReadOnly = footprint.readOnly().length > 0 && footprint.readWrite().length === 0;
|
|
64
|
+
if (isReadOnly) {
|
|
65
|
+
response.isReadOnly = true;
|
|
66
|
+
response.result = result;
|
|
67
|
+
return response;
|
|
68
|
+
}
|
|
69
|
+
// For write operations, continue with the normal flow of returning the XDR
|
|
70
|
+
const preparedTransaction = await server.prepareTransaction(builtTransaction);
|
|
71
|
+
response.result = preparedTransaction.toXDR();
|
|
72
|
+
return response;
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
if (rpc.Api.isSimulationError(sim)) {
|
|
76
|
+
throw new Error(`Tansaction simulation error: ${JSON.stringify(sim.error)}`);
|
|
77
|
+
}
|
|
78
|
+
throw new Error('Transaction simulation failed');
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
const signTransaction = async (context, xdrToSign, privateKey) => {
|
|
82
|
+
const preparedTransaction = TransactionBuilder.fromXDR(xdrToSign, context.network.networkPassphrase);
|
|
83
|
+
const sourceKeypair = Keypair.fromSecret(privateKey);
|
|
84
|
+
preparedTransaction.sign(sourceKeypair);
|
|
85
|
+
return preparedTransaction;
|
|
86
|
+
};
|
|
87
|
+
const sendTransaction = async (context, signedTransactionXDR) => {
|
|
88
|
+
const server = getServer(context.network);
|
|
89
|
+
const signedTransaction = TransactionBuilder.fromXDR(signedTransactionXDR, context.network.networkPassphrase);
|
|
90
|
+
// Submit the transaction to the Stellar-RPC server. The RPC server will
|
|
91
|
+
// then submit the transaction into the network for us. Then we will have to
|
|
92
|
+
// wait, polling `getTransaction` until the transaction completes.
|
|
93
|
+
try {
|
|
94
|
+
const sendResponse = await server.sendTransaction(signedTransaction);
|
|
95
|
+
if (sendResponse.status === 'PENDING') {
|
|
96
|
+
let getResponse = await server.getTransaction(sendResponse.hash);
|
|
97
|
+
// Poll `getTransaction` until the status is not "NOT_FOUND"
|
|
98
|
+
while (getResponse.status === 'NOT_FOUND') {
|
|
99
|
+
// See if the transaction is complete
|
|
100
|
+
getResponse = await server.getTransaction(sendResponse.hash);
|
|
101
|
+
// Wait one second
|
|
102
|
+
await sleep(1000);
|
|
103
|
+
}
|
|
104
|
+
//console.log(`getTransaction response: ${JSON.stringify(getResponse)}`);
|
|
105
|
+
if (getResponse.status === 'SUCCESS') {
|
|
106
|
+
// Make sure the transaction's resultMetaXDR is not empty
|
|
107
|
+
if (!getResponse.resultMetaXdr) {
|
|
108
|
+
throw new Error('Empty resultMetaXDR in getTransaction response');
|
|
109
|
+
}
|
|
110
|
+
// Find the return value from the contract and return it
|
|
111
|
+
const transactionMeta = getResponse.resultMetaXdr;
|
|
112
|
+
const returnValue = transactionMeta.v3().sorobanMeta()?.returnValue();
|
|
113
|
+
if (returnValue) {
|
|
114
|
+
return scValToNative(returnValue);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
throw new Error(`Transaction failed: ${getResponse.resultXdr}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
throw new Error(sendResponse.errorResult?.toString() || 'Unknown error');
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
// Catch and report any errors we've thrown
|
|
127
|
+
throw new Error(`Transaction sending error: ${JSON.stringify(err)}`);
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
export { prepareTransaction, sendTransaction, signTransaction, getNetwork, getPublicKeyFromPrivateKey, };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ClientContext } from './client.js';
|
|
2
|
+
import { DeletionStatus, StorageReservation, StorageUnit } from './models.js';
|
|
3
|
+
type RegisterUnitResponse = [unitId: number, unit: StorageUnit];
|
|
4
|
+
declare const get_unit: (context: ClientContext, wallet_address: string, unit_id: number, load_reservations?: boolean) => Promise<StorageUnit | null>;
|
|
5
|
+
declare const get_unit_reservations: (context: ClientContext, wallet_address: string, unit_id: number) => Promise<Map<number, StorageReservation>>;
|
|
6
|
+
declare const register_unit: (context: ClientContext, wallet_address: string, provider_address: string, capacity: number, endpoint: string) => Promise<RegisterUnitResponse | null>;
|
|
7
|
+
declare const delete_unit: (context: ClientContext, wallet_address: string, provider_address: string, unit_id: number) => Promise<DeletionStatus | null>;
|
|
8
|
+
declare const enter_maintenance: (context: ClientContext, wallet_address: string, provider_address: string, unit_id: number, maintenanceStart: Date, maintenanceEnd: Date) => Promise<boolean | null>;
|
|
9
|
+
declare const exit_maintenance: (context: ClientContext, wallet_address: string, provider_address: string, unit_id: number) => Promise<boolean | null>;
|
|
10
|
+
declare const enter_decommissioning: (context: ClientContext, wallet_address: string, provider_address: string, unit_id: number) => Promise<boolean | null>;
|
|
11
|
+
declare const exit_decommissioning: (context: ClientContext, wallet_address: string, provider_address: string, unit_id: number) => Promise<boolean | null>;
|
|
12
|
+
export { get_unit, get_unit_reservations, register_unit, delete_unit, enter_maintenance, exit_maintenance, enter_decommissioning, exit_decommissioning, };
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { prepareTransaction, sendTransaction } from './transaction.js';
|
|
2
|
+
const get_unit = async (context, wallet_address, unit_id, load_reservations = false) => {
|
|
3
|
+
const [unit, reservations] = await Promise.all([
|
|
4
|
+
prepareTransaction(context, wallet_address, {
|
|
5
|
+
method: 'get_unit',
|
|
6
|
+
args: [{ value: unit_id, type: 'u32' }],
|
|
7
|
+
}),
|
|
8
|
+
load_reservations
|
|
9
|
+
? get_unit_reservations(context, wallet_address, unit_id)
|
|
10
|
+
: new Map(),
|
|
11
|
+
]);
|
|
12
|
+
const typedUnitData = unit.isSuccess ? unit.result : null;
|
|
13
|
+
if (typedUnitData) {
|
|
14
|
+
typedUnitData.reservations = reservations;
|
|
15
|
+
}
|
|
16
|
+
return typedUnitData;
|
|
17
|
+
};
|
|
18
|
+
const get_unit_reservations = async (context, wallet_address, unit_id) => {
|
|
19
|
+
const response = await prepareTransaction(context, wallet_address, {
|
|
20
|
+
method: 'get_unit_reservations',
|
|
21
|
+
args: [{ value: unit_id, type: 'u32' }],
|
|
22
|
+
});
|
|
23
|
+
const typedUnitReservations = response.isSuccess
|
|
24
|
+
? response.result
|
|
25
|
+
: new Map();
|
|
26
|
+
return typedUnitReservations;
|
|
27
|
+
};
|
|
28
|
+
const executeUnitTransaction = async (context, wallet_address, provider_address, method, additionalArgs = []) => {
|
|
29
|
+
const isOwner = wallet_address !== provider_address;
|
|
30
|
+
const response = await prepareTransaction(context, wallet_address, {
|
|
31
|
+
method,
|
|
32
|
+
args: [
|
|
33
|
+
{ value: provider_address, type: 'address' },
|
|
34
|
+
...additionalArgs,
|
|
35
|
+
{ value: isOwner, type: 'bool' },
|
|
36
|
+
],
|
|
37
|
+
});
|
|
38
|
+
if (response.isSuccess && !response.isReadOnly) {
|
|
39
|
+
const signedTxXDR = await context.signTransaction(response.result);
|
|
40
|
+
return sendTransaction(context, signedTxXDR);
|
|
41
|
+
}
|
|
42
|
+
return null;
|
|
43
|
+
};
|
|
44
|
+
const register_unit = async (context, wallet_address, provider_address, capacity, endpoint) => {
|
|
45
|
+
return executeUnitTransaction(context, wallet_address, provider_address, 'register_unit', [
|
|
46
|
+
{ value: capacity, type: 'u32' },
|
|
47
|
+
{ value: endpoint, type: 'string' },
|
|
48
|
+
]);
|
|
49
|
+
};
|
|
50
|
+
const delete_unit = async (context, wallet_address, provider_address, unit_id) => {
|
|
51
|
+
return executeUnitTransaction(context, wallet_address, provider_address, 'delete_unit', [{ value: unit_id, type: 'u32' }]);
|
|
52
|
+
};
|
|
53
|
+
const change_unit_status = async (context, method, wallet_address, provider_address, unit_id, maintenanceStart, maintenanceEnd) => {
|
|
54
|
+
const isOwner = wallet_address !== provider_address;
|
|
55
|
+
const response = await prepareTransaction(context, wallet_address, {
|
|
56
|
+
method: method,
|
|
57
|
+
args: [
|
|
58
|
+
{ value: provider_address, type: 'address' },
|
|
59
|
+
{ value: unit_id, type: 'u32' },
|
|
60
|
+
...(method === 'enter_maintenance'
|
|
61
|
+
? [
|
|
62
|
+
{ value: Math.floor(maintenanceStart.getTime() / 1000), type: 'u64' },
|
|
63
|
+
{ value: Math.floor(maintenanceEnd.getTime() / 1000), type: 'u64' },
|
|
64
|
+
]
|
|
65
|
+
: []),
|
|
66
|
+
{ value: isOwner, type: 'bool' },
|
|
67
|
+
],
|
|
68
|
+
});
|
|
69
|
+
if (response.isSuccess && !response.isReadOnly) {
|
|
70
|
+
const signedTxXDR = await context.signTransaction(response.result);
|
|
71
|
+
const responseSend = (await sendTransaction(context, signedTxXDR));
|
|
72
|
+
return responseSend;
|
|
73
|
+
}
|
|
74
|
+
return null;
|
|
75
|
+
};
|
|
76
|
+
const createUnitMaintenanceChanger = (method) => {
|
|
77
|
+
return async (context, wallet_address, provider_address, unit_id, maintenanceStart, maintenanceEnd) => {
|
|
78
|
+
return change_unit_status(context, method, wallet_address, provider_address, unit_id, maintenanceStart, maintenanceEnd);
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
const createUnitStatusChanger = (method) => {
|
|
82
|
+
return async (context, wallet_address, provider_address, unit_id) => {
|
|
83
|
+
return change_unit_status(context, method, wallet_address, provider_address, unit_id);
|
|
84
|
+
};
|
|
85
|
+
};
|
|
86
|
+
const enter_maintenance = createUnitMaintenanceChanger('enter_maintenance');
|
|
87
|
+
const exit_maintenance = createUnitStatusChanger('exit_maintenance');
|
|
88
|
+
const enter_decommissioning = createUnitStatusChanger('enter_decommissioning');
|
|
89
|
+
const exit_decommissioning = createUnitStatusChanger('exit_decommissioning');
|
|
90
|
+
export { get_unit, get_unit_reservations, register_unit, delete_unit, enter_maintenance, exit_maintenance, enter_decommissioning, exit_decommissioning, };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const sleep: (ms: number) => Promise<void>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const getGlobalThis = () => {
|
|
2
|
+
if (typeof globalThis !== 'undefined')
|
|
3
|
+
return globalThis;
|
|
4
|
+
if (typeof self !== 'undefined')
|
|
5
|
+
return self;
|
|
6
|
+
if (typeof window !== 'undefined')
|
|
7
|
+
return window;
|
|
8
|
+
if (typeof global !== 'undefined')
|
|
9
|
+
return global;
|
|
10
|
+
throw new Error('Unable to locate global object');
|
|
11
|
+
};
|
|
12
|
+
export const sleep = (ms) => {
|
|
13
|
+
const globalScope = getGlobalThis();
|
|
14
|
+
return new Promise((resolve) => globalScope.setTimeout(resolve, ms));
|
|
15
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@flashbacktech/flashbackclient",
|
|
3
|
+
"version": "0.0.13",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"description": "",
|
|
8
|
+
"main": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"scripts": {
|
|
11
|
+
"dev": "tsc",
|
|
12
|
+
"dev:watch": "nodemon --exec 'npm run dev || exit 1'",
|
|
13
|
+
"lint": "eslint . --ext .ts",
|
|
14
|
+
"build": "npm run dev",
|
|
15
|
+
"test": "jest",
|
|
16
|
+
"test:watch": "jest --watch",
|
|
17
|
+
"test:coverage": "jest --coverage",
|
|
18
|
+
"clean": "rm -rf dist",
|
|
19
|
+
"format": "eslint \"**/*.ts\" --ignore-pattern 'dist/**' --fix && prettier --write . --ignore-path .gitignore",
|
|
20
|
+
"docs": "typedoc",
|
|
21
|
+
"pub": "npm run build && npm version patch && npm publish --access public"
|
|
22
|
+
},
|
|
23
|
+
"author": "Javier Ortiz <javier.ortiz@flashback.tech>",
|
|
24
|
+
"license": "ISC",
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@stellar/stellar-sdk": "^13.0.0"
|
|
27
|
+
},
|
|
28
|
+
"bin": {
|
|
29
|
+
"": "./dist/.min.js"
|
|
30
|
+
},
|
|
31
|
+
"exports": {
|
|
32
|
+
"./stellar": {
|
|
33
|
+
"types": "./dist/stellar/index.d.ts",
|
|
34
|
+
"import": "./dist/stellar/index.js",
|
|
35
|
+
"default": "./dist/stellar/index.js"
|
|
36
|
+
},
|
|
37
|
+
"./path2": {
|
|
38
|
+
"types": "./dist/path2/index.d.ts",
|
|
39
|
+
"import": "./dist/path2/index.js",
|
|
40
|
+
"default": "./dist/path2/index.js"
|
|
41
|
+
},
|
|
42
|
+
"./path3": {
|
|
43
|
+
"types": "./dist/path3/index.d.ts",
|
|
44
|
+
"import": "./dist/path3/index.js",
|
|
45
|
+
"default": "./dist/path3/index.js"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"files": [
|
|
49
|
+
"dist"
|
|
50
|
+
],
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@eslint/js": "^8.56.0",
|
|
53
|
+
"@types/jest": "^29.5.14",
|
|
54
|
+
"@types/node": "^22.10.1",
|
|
55
|
+
"@typescript-eslint/eslint-plugin": "^8.17.0",
|
|
56
|
+
"@typescript-eslint/parser": "^8.17.0",
|
|
57
|
+
"dotenv": "^16.4.7",
|
|
58
|
+
"eslint": "^9.16.0",
|
|
59
|
+
"eslint-config-prettier": "^9.1.0",
|
|
60
|
+
"eslint-plugin-prettier": "^5.2.1",
|
|
61
|
+
"jest": "^29.7.0",
|
|
62
|
+
"prettier": "^3.4.1",
|
|
63
|
+
"ts-jest": "^29.2.5",
|
|
64
|
+
"ts-node-dev": "^2.0.0",
|
|
65
|
+
"typescript": "^5.7.2"
|
|
66
|
+
},
|
|
67
|
+
"type": "module",
|
|
68
|
+
"typesVersions": {
|
|
69
|
+
"*": {
|
|
70
|
+
"stellar": [
|
|
71
|
+
"./dist/stellar/index.d.ts"
|
|
72
|
+
],
|
|
73
|
+
"path2": [
|
|
74
|
+
"./dist/path2/index.d.ts"
|
|
75
|
+
],
|
|
76
|
+
"path3": [
|
|
77
|
+
"./dist/path3/index.d.ts"
|
|
78
|
+
]
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|