@dynamic-labs-sdk/solana 0.1.0-alpha.3 → 0.1.0-alpha.30
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/CHANGELOG.md +303 -0
- package/addSolanaWalletStandardExtension.cjs.js +118 -156
- package/addSolanaWalletStandardExtension.esm.js +121 -159
- package/addWaasSolanaExtension.cjs.js +60 -74
- package/addWaasSolanaExtension.esm.js +62 -76
- package/index.cjs.js +66 -21
- package/index.esm.js +64 -21
- package/isVersionedTransaction.cjs.js +1 -42
- package/isVersionedTransaction.esm.js +2 -42
- package/package.json +5 -5
- package/src/SolanaWalletProvider.types.d.ts +21 -3
- package/src/SolanaWalletProvider.types.d.ts.map +1 -1
- package/src/exports/index.d.ts +3 -1
- package/src/exports/index.d.ts.map +1 -1
- package/src/signAllTransactions/index.d.ts +2 -0
- package/src/signAllTransactions/index.d.ts.map +1 -0
- package/src/signAllTransactions/signAllTransactions.d.ts +18 -0
- package/src/signAllTransactions/signAllTransactions.d.ts.map +1 -0
- package/src/signAndSendTransaction/index.d.ts +2 -0
- package/src/signAndSendTransaction/index.d.ts.map +1 -0
- package/src/signAndSendTransaction/signAndSendTransaction.d.ts +18 -0
- package/src/signAndSendTransaction/signAndSendTransaction.d.ts.map +1 -0
- package/src/signTransaction/index.d.ts +2 -0
- package/src/signTransaction/index.d.ts.map +1 -0
- package/src/signTransaction/signTransaction.d.ts +18 -0
- package/src/signTransaction/signTransaction.d.ts.map +1 -0
- package/src/utils/createSolanaNetworkProvider/createSolanaNetworkProvider.d.ts.map +1 -1
- package/src/waas/utils/createWalletProviderForWaasSolana/createWalletProviderForWaasSolana.d.ts.map +1 -1
- package/src/walletStandard/utils/createWalletProviderFromSolanaStandardWallet/createWalletProviderFromSolanaStandardWallet.d.ts.map +1 -1
- package/src/walletStandard/utils/getActiveNetworkCluster/getActiveNetworkCluster.d.ts +7 -0
- package/src/walletStandard/utils/getActiveNetworkCluster/getActiveNetworkCluster.d.ts.map +1 -0
- package/src/walletStandard/utils/getActiveNetworkCluster/index.d.ts +2 -0
- package/src/walletStandard/utils/getActiveNetworkCluster/index.d.ts.map +1 -0
- package/waas.cjs.js +0 -1
- package/waas.esm.js +0 -1
- package/src/SolanaSigner.types.d.ts +0 -40
- package/src/SolanaSigner.types.d.ts.map +0 -1
- package/src/getSigner/getSigner.d.ts +0 -16
- package/src/getSigner/getSigner.d.ts.map +0 -1
- package/src/getSigner/index.d.ts +0 -2
- package/src/getSigner/index.d.ts.map +0 -1
- package/src/waas/utils/createSolanaSignerFromSolanaWaasProvider/createSolanaSignerFromSolanaWaasProvider.d.ts +0 -11
- package/src/waas/utils/createSolanaSignerFromSolanaWaasProvider/createSolanaSignerFromSolanaWaasProvider.d.ts.map +0 -1
- package/src/waas/utils/createSolanaSignerFromSolanaWaasProvider/index.d.ts +0 -2
- package/src/waas/utils/createSolanaSignerFromSolanaWaasProvider/index.d.ts.map +0 -1
- package/src/walletStandard/utils/createSolanaSignerFromSolanaStandardWallet/createSolanaSignerFromSolanaStandardWallet.d.ts +0 -10
- package/src/walletStandard/utils/createSolanaSignerFromSolanaStandardWallet/createSolanaSignerFromSolanaStandardWallet.d.ts.map +0 -1
- package/src/walletStandard/utils/createSolanaSignerFromSolanaStandardWallet/index.d.ts +0 -2
- package/src/walletStandard/utils/createSolanaSignerFromSolanaStandardWallet/index.d.ts.map +0 -1
|
@@ -24,6 +24,7 @@ const fetchSolBalance = async ({ address, rpcUrl })=>{
|
|
|
24
24
|
|
|
25
25
|
const createSolanaNetworkProvider = (networkData)=>isVersionedTransaction._extends({}, core.createBaseNetworkProvider('SOL', networkData), {
|
|
26
26
|
cluster: networkData.cluster,
|
|
27
|
+
genesisHash: networkData.genesisHash,
|
|
27
28
|
getBalance: async ({ address })=>({
|
|
28
29
|
balance: await fetchSolBalance({
|
|
29
30
|
address,
|
|
@@ -45,36 +46,28 @@ const registerSolanaNetworkProviderBuilder = (client)=>{
|
|
|
45
46
|
});
|
|
46
47
|
};
|
|
47
48
|
|
|
49
|
+
const getActiveNetworkCluster = async ({ walletAccount }, client$1)=>{
|
|
50
|
+
const { networkData } = await client.getActiveNetworkData({
|
|
51
|
+
walletAccount
|
|
52
|
+
}, client$1);
|
|
53
|
+
if (!(networkData == null ? void 0 : networkData.cluster)) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
return `solana:${networkData.cluster}`;
|
|
57
|
+
};
|
|
58
|
+
|
|
48
59
|
const getFeaturesForSolanaStandardWallet = (wallet)=>{
|
|
49
60
|
return wallet.features;
|
|
50
61
|
};
|
|
51
62
|
|
|
52
|
-
const
|
|
63
|
+
const createWalletProviderFromSolanaStandardWallet = ({ dynamicClient, walletStandardWallet })=>{
|
|
53
64
|
const features = getFeaturesForSolanaStandardWallet(walletStandardWallet);
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
};
|
|
61
|
-
const getChain = ()=>{
|
|
62
|
-
core.assertDefined(networkProvider.cluster, `Cluster was not defined for network provider ${networkProvider.displayName} (networkId: ${networkProvider.networkId})`);
|
|
63
|
-
return `solana:${networkProvider.cluster}`;
|
|
64
|
-
};
|
|
65
|
-
const isConnected = ()=>{
|
|
66
|
-
var _walletStandardWallet_accounts;
|
|
67
|
-
return ((_walletStandardWallet_accounts = walletStandardWallet.accounts) == null ? void 0 : _walletStandardWallet_accounts.length) > 0;
|
|
68
|
-
};
|
|
69
|
-
const getCurrentAccount = async ()=>{
|
|
70
|
-
var _walletStandardWallet_accounts;
|
|
71
|
-
if (!isConnected()) {
|
|
72
|
-
await connect();
|
|
73
|
-
}
|
|
74
|
-
const account = (_walletStandardWallet_accounts = walletStandardWallet.accounts) == null ? void 0 : _walletStandardWallet_accounts[0];
|
|
75
|
-
core.assertDefined(account, 'No connected accounts found');
|
|
76
|
-
return account;
|
|
77
|
-
};
|
|
65
|
+
const walletProviderType = sdkApiCore.WalletProviderEnum.BrowserExtension;
|
|
66
|
+
const key = core.formatWalletProviderKey({
|
|
67
|
+
chain: 'SOL',
|
|
68
|
+
displayName: walletStandardWallet.name,
|
|
69
|
+
walletProviderType
|
|
70
|
+
});
|
|
78
71
|
const connect = async ()=>{
|
|
79
72
|
var _features_standardconnect, _result_accounts;
|
|
80
73
|
const autoConnectedAccounts = walletStandardWallet.accounts;
|
|
@@ -83,8 +76,12 @@ const createSolanaSignerFromSolanaStandardWallet = ({ networkProvider, walletSta
|
|
|
83
76
|
// so we need to check for that first
|
|
84
77
|
if ((autoConnectedAccounts == null ? void 0 : autoConnectedAccounts.length) && autoConnectedAccounts[0].publicKey && autoConnectedAccounts[0].address) {
|
|
85
78
|
return {
|
|
86
|
-
|
|
87
|
-
|
|
79
|
+
addresses: [
|
|
80
|
+
{
|
|
81
|
+
address: autoConnectedAccounts[0].address,
|
|
82
|
+
publicKey: autoConnectedAccounts[0].publicKey.toString()
|
|
83
|
+
}
|
|
84
|
+
]
|
|
88
85
|
};
|
|
89
86
|
}
|
|
90
87
|
const connectMethod = (_features_standardconnect = features['standard:connect']) == null ? void 0 : _features_standardconnect.connect;
|
|
@@ -92,11 +89,14 @@ const createSolanaSignerFromSolanaStandardWallet = ({ networkProvider, walletSta
|
|
|
92
89
|
const result = await connectMethod({
|
|
93
90
|
silent: false
|
|
94
91
|
});
|
|
95
|
-
const connectedAccount = result == null ? void 0 : (_result_accounts = result.accounts) == null ? void 0 : _result_accounts[0];
|
|
96
|
-
core.assertDefined(connectedAccount, 'No connected accounts');
|
|
97
92
|
return {
|
|
98
|
-
|
|
99
|
-
|
|
93
|
+
addresses: (_result_accounts = result.accounts) == null ? void 0 : _result_accounts.map((account)=>{
|
|
94
|
+
var _account_publicKey;
|
|
95
|
+
return {
|
|
96
|
+
address: account.address,
|
|
97
|
+
publicKey: (_account_publicKey = account.publicKey) == null ? void 0 : _account_publicKey.toString()
|
|
98
|
+
};
|
|
99
|
+
})
|
|
100
100
|
};
|
|
101
101
|
};
|
|
102
102
|
const disconnect = async ()=>{
|
|
@@ -105,53 +105,58 @@ const createSolanaSignerFromSolanaStandardWallet = ({ networkProvider, walletSta
|
|
|
105
105
|
core.assertDefined(disconnectMethod, 'disconnect method not found in wallet features');
|
|
106
106
|
await disconnectMethod();
|
|
107
107
|
};
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
108
|
+
const getActiveNetworkId = async ()=>core.getActiveNetworkIdFromLastKnownRegistry({
|
|
109
|
+
client: dynamicClient,
|
|
110
|
+
walletProviderKey: key
|
|
111
|
+
});
|
|
112
|
+
const getCurrentAccount = async ()=>{
|
|
113
|
+
var _walletStandardWallet_accounts;
|
|
114
|
+
if (!isConnected() && connect) {
|
|
115
|
+
await connect();
|
|
113
116
|
}
|
|
114
|
-
|
|
115
|
-
|
|
117
|
+
const account = (_walletStandardWallet_accounts = walletStandardWallet.accounts) == null ? void 0 : _walletStandardWallet_accounts[0];
|
|
118
|
+
core.assertDefined(account, 'No connected accounts found');
|
|
119
|
+
return account;
|
|
120
|
+
};
|
|
121
|
+
const isConnected = ()=>{
|
|
122
|
+
var _walletStandardWallet_accounts;
|
|
123
|
+
return ((_walletStandardWallet_accounts = walletStandardWallet.accounts) == null ? void 0 : _walletStandardWallet_accounts.length) > 0;
|
|
124
|
+
};
|
|
125
|
+
const getConnectedAddresses = async ()=>{
|
|
126
|
+
if (!isConnected() && connect) {
|
|
127
|
+
await connect();
|
|
116
128
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
const publicKey = (_prop_accounts = prop.accounts) == null ? void 0 : (_prop_accounts_ = _prop_accounts[0]) == null ? void 0 : _prop_accounts_.publicKey;
|
|
120
|
-
if (publicKey) {
|
|
121
|
-
listener(new TextDecoder().decode(publicKey));
|
|
122
|
-
}
|
|
129
|
+
return {
|
|
130
|
+
addresses: walletStandardWallet.accounts.map((account)=>account.address)
|
|
123
131
|
};
|
|
124
|
-
// 'change' is the only event that is supported by the wallet standard
|
|
125
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
126
|
-
return onMethod('change', wrappedListener);
|
|
127
132
|
};
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
});
|
|
140
|
-
const signedTransaction = signTransactionResult[0].signedTransaction;
|
|
141
|
-
if (isVersionedTransaction.isVersionedTransaction(transaction)) {
|
|
142
|
-
return web3_js.VersionedTransaction.deserialize(signedTransaction);
|
|
143
|
-
}
|
|
144
|
-
return web3_js.Transaction.from(signedTransaction);
|
|
133
|
+
const signAllTransactions = async ({ transactions, walletAccount })=>{
|
|
134
|
+
const signedTransactions = await Promise.all(transactions.map(async (transaction)=>{
|
|
135
|
+
const { signedTransaction } = await signTransaction({
|
|
136
|
+
transaction,
|
|
137
|
+
walletAccount
|
|
138
|
+
});
|
|
139
|
+
return signedTransaction;
|
|
140
|
+
}));
|
|
141
|
+
return {
|
|
142
|
+
signedTransactions
|
|
143
|
+
};
|
|
145
144
|
};
|
|
146
|
-
const
|
|
147
|
-
const signAndSendTransaction = async (transaction)=>{
|
|
145
|
+
const signAndSendTransaction = async ({ transaction, walletAccount })=>{
|
|
148
146
|
var _features_solanasignAndSendTransaction;
|
|
147
|
+
await client.assertWalletAccountSigningAvailability({
|
|
148
|
+
walletAccount
|
|
149
|
+
}, dynamicClient);
|
|
149
150
|
const signAndSendTransactionMethod = (_features_solanasignAndSendTransaction = features['solana:signAndSendTransaction']) == null ? void 0 : _features_solanasignAndSendTransaction.signAndSendTransaction;
|
|
150
151
|
core.assertDefined(signAndSendTransactionMethod, 'signAndSendTransaction method not found in wallet features');
|
|
151
152
|
const account = await getCurrentAccount();
|
|
153
|
+
const chain = await getActiveNetworkCluster({
|
|
154
|
+
walletAccount
|
|
155
|
+
}, dynamicClient);
|
|
156
|
+
core.assertDefined(chain, 'Could not get active chain for wallet account');
|
|
152
157
|
const signedTransactions = await signAndSendTransactionMethod({
|
|
153
158
|
account,
|
|
154
|
-
chain
|
|
159
|
+
chain,
|
|
155
160
|
transaction: transaction.serialize({
|
|
156
161
|
requireAllSignatures: false
|
|
157
162
|
})
|
|
@@ -161,107 +166,66 @@ const createSolanaSignerFromSolanaStandardWallet = ({ networkProvider, walletSta
|
|
|
161
166
|
signature: bs58.encode(signature)
|
|
162
167
|
};
|
|
163
168
|
};
|
|
164
|
-
const signMessage = async (message)=>{
|
|
169
|
+
const signMessage = async ({ message, walletAccount })=>{
|
|
165
170
|
var _features_solanasignMessage;
|
|
166
171
|
const signMessageMethod = (_features_solanasignMessage = features['solana:signMessage']) == null ? void 0 : _features_solanasignMessage.signMessage;
|
|
167
172
|
core.assertDefined(signMessageMethod, 'signMessage method not found in wallet features');
|
|
173
|
+
core.assertDefined(walletAccount, 'Wallet account not found');
|
|
174
|
+
await client.assertWalletAccountSigningAvailability({
|
|
175
|
+
walletAccount
|
|
176
|
+
}, dynamicClient);
|
|
177
|
+
const encodedMessage = new TextEncoder().encode(message);
|
|
168
178
|
const account = await getCurrentAccount();
|
|
169
179
|
const messages = await signMessageMethod({
|
|
170
180
|
account,
|
|
171
|
-
message
|
|
181
|
+
message: encodedMessage
|
|
172
182
|
});
|
|
173
183
|
return {
|
|
174
|
-
signature: messages[0].signature
|
|
184
|
+
signature: core.bufferToBase64(messages[0].signature)
|
|
175
185
|
};
|
|
176
186
|
};
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
},
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
const createWalletProviderFromSolanaStandardWallet = ({ dynamicClient, walletStandardWallet })=>{
|
|
196
|
-
const key = core.formatWalletProviderKey(walletStandardWallet.name, 'SOL');
|
|
197
|
-
const getActiveNetworkId = async ()=>core.getActiveNetworkIdFromLastKnownRegistry({
|
|
198
|
-
client: dynamicClient,
|
|
199
|
-
walletProviderKey: key
|
|
200
|
-
});
|
|
201
|
-
const switchActiveNetwork = async ({ networkId })=>core.switchActiveNetworkInLastKnownRegistry({
|
|
202
|
-
client: dynamicClient,
|
|
203
|
-
networkId,
|
|
204
|
-
walletProviderKey: key
|
|
187
|
+
const signTransaction = async ({ transaction, walletAccount })=>{
|
|
188
|
+
var _features_solanasignTransaction;
|
|
189
|
+
const signMessageMethod = (_features_solanasignTransaction = features['solana:signTransaction']) == null ? void 0 : _features_solanasignTransaction.signTransaction;
|
|
190
|
+
core.assertDefined(signMessageMethod, 'signTransaction method not found in wallet features');
|
|
191
|
+
await client.assertWalletAccountSigningAvailability({
|
|
192
|
+
walletAccount
|
|
193
|
+
}, dynamicClient);
|
|
194
|
+
const account = await getCurrentAccount();
|
|
195
|
+
const chain = await getActiveNetworkCluster({
|
|
196
|
+
walletAccount
|
|
197
|
+
}, dynamicClient);
|
|
198
|
+
core.assertDefined(chain, 'Could not get active chain for wallet account');
|
|
199
|
+
const signTransactionResult = await signMessageMethod({
|
|
200
|
+
account,
|
|
201
|
+
chain,
|
|
202
|
+
transaction: transaction.serialize({
|
|
203
|
+
requireAllSignatures: false
|
|
204
|
+
})
|
|
205
205
|
});
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
result.address
|
|
212
|
-
] : []
|
|
213
|
-
};
|
|
214
|
-
};
|
|
215
|
-
const disconnect = async ()=>{
|
|
216
|
-
const signer = await getSigner();
|
|
217
|
-
await signer.disconnect();
|
|
218
|
-
};
|
|
219
|
-
const getConnectedAddresses = async ()=>{
|
|
220
|
-
const signer = await getSigner();
|
|
221
|
-
if (!signer.isConnected) {
|
|
222
|
-
await signer.connect();
|
|
206
|
+
const signedTransaction = signTransactionResult[0].signedTransaction;
|
|
207
|
+
if (isVersionedTransaction.isVersionedTransaction(transaction)) {
|
|
208
|
+
return {
|
|
209
|
+
signedTransaction: web3_js.VersionedTransaction.deserialize(signedTransaction)
|
|
210
|
+
};
|
|
223
211
|
}
|
|
224
212
|
return {
|
|
225
|
-
|
|
213
|
+
signedTransaction: web3_js.Transaction.from(signedTransaction)
|
|
226
214
|
};
|
|
227
215
|
};
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
}, dynamicClient);
|
|
233
|
-
}
|
|
234
|
-
const { networkId } = await getActiveNetworkId();
|
|
235
|
-
const networkProvider = core.getNetworkProviderFromNetworkId({
|
|
236
|
-
chain: 'SOL',
|
|
237
|
-
networkId
|
|
238
|
-
}, dynamicClient);
|
|
239
|
-
return createSolanaSignerFromSolanaStandardWallet({
|
|
240
|
-
networkProvider,
|
|
241
|
-
walletStandardWallet
|
|
216
|
+
const switchActiveNetwork = async ({ networkId })=>core.switchActiveNetworkInLastKnownRegistry({
|
|
217
|
+
client: dynamicClient,
|
|
218
|
+
networkId,
|
|
219
|
+
walletProviderKey: key
|
|
242
220
|
});
|
|
243
|
-
};
|
|
244
|
-
const signMessage = async ({ message, walletAccount })=>{
|
|
245
|
-
const signer = await getSigner(walletAccount);
|
|
246
|
-
const encodedMessage = new TextEncoder().encode(message);
|
|
247
|
-
const signedMessage = await signer.signMessage(encodedMessage, 'utf8');
|
|
248
|
-
core.assertDefined(signedMessage, 'Failed to sign message');
|
|
249
|
-
return {
|
|
250
|
-
signature: core.bufferToBase64(signedMessage.signature)
|
|
251
|
-
};
|
|
252
|
-
};
|
|
253
|
-
const getEventsFeature = ()=>{
|
|
254
|
-
const features = getFeaturesForSolanaStandardWallet(walletStandardWallet);
|
|
255
|
-
const eventsFeature = features['standard:events'];
|
|
256
|
-
return eventsFeature;
|
|
257
|
-
};
|
|
258
221
|
const { getEventEmitter, cleanupEventEmitter } = core.createWalletProviderEventEmitter({
|
|
259
222
|
removeEventListeners: ({ setupReturnValue })=>{
|
|
260
223
|
core.assertDefined(setupReturnValue, 'Setup return value not defined');
|
|
261
224
|
setupReturnValue();
|
|
262
225
|
},
|
|
263
226
|
setupEventListeners: ({ handleAccountsChanged })=>{
|
|
264
|
-
|
|
227
|
+
const eventsFeature = features['standard:events'];
|
|
228
|
+
return eventsFeature.on('change', ({ accounts })=>{
|
|
265
229
|
var _accounts_map;
|
|
266
230
|
handleAccountsChanged({
|
|
267
231
|
addresses: (_accounts_map = accounts == null ? void 0 : accounts.map((account)=>account.address)) != null ? _accounts_map : []
|
|
@@ -279,27 +243,25 @@ const createWalletProviderFromSolanaStandardWallet = ({ dynamicClient, walletSta
|
|
|
279
243
|
chain: 'SOL',
|
|
280
244
|
connect,
|
|
281
245
|
disconnect,
|
|
246
|
+
get events () {
|
|
247
|
+
return getEventEmitter();
|
|
248
|
+
},
|
|
282
249
|
getActiveNetworkId,
|
|
283
250
|
getConnectedAddresses,
|
|
284
|
-
getSigner,
|
|
285
|
-
getWalletProviderType: ()=>sdkApiCore.WalletProviderEnum.BrowserExtension,
|
|
286
251
|
groupKey: core.formatWalletProviderGroupKey(walletStandardWallet.name),
|
|
287
252
|
key,
|
|
288
253
|
metadata: {
|
|
289
254
|
displayName: walletStandardWallet.name,
|
|
290
255
|
icon: walletStandardWallet.icon
|
|
291
256
|
},
|
|
257
|
+
signAllTransactions,
|
|
258
|
+
signAndSendTransaction,
|
|
292
259
|
signMessage,
|
|
260
|
+
signTransaction,
|
|
293
261
|
switchActiveNetwork,
|
|
294
|
-
terminate
|
|
262
|
+
terminate,
|
|
263
|
+
walletProviderType
|
|
295
264
|
};
|
|
296
|
-
// The provider will only implement events if this external wallet provider
|
|
297
|
-
// implements the standard:events feature
|
|
298
|
-
if (getEventsFeature()) {
|
|
299
|
-
Object.defineProperty(walletProvider, 'events', {
|
|
300
|
-
get: ()=>getEventEmitter()
|
|
301
|
-
});
|
|
302
|
-
}
|
|
303
265
|
return walletProvider;
|
|
304
266
|
};
|
|
305
267
|
|