@stellar/typescript-wallet-sdk 5.1.0 → 6.0.0-beta.1793996806758
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 +14 -0
- package/lib/bundle.js +1801 -435
- package/lib/bundle.js.map +1 -1
- package/lib/bundle_browser.js +1801 -435
- package/lib/bundle_browser.js.map +1 -1
- package/lib/walletSdk/Exceptions/index.d.ts +3 -0
- package/lib/walletSdk/Uri/Sep7Pay.d.ts +10 -0
- package/package.json +3 -3
- package/src/walletSdk/Exceptions/index.ts +9 -0
- package/src/walletSdk/Uri/Sep7Pay.ts +42 -1
- package/src/walletSdk/Uri/sep7Parser.ts +18 -2
- package/test/accountService.test.ts +3 -2
- package/test/auth.test.ts +51 -0
- package/test/e2e/reactNative.test.ts +112 -1
- package/test/fixtures/muxedContract.ts +47 -0
- package/test/integration/anchorplatform.test.ts +2 -1
- package/test/integration/recovery.test.ts +10 -10
- package/test/sep6.test.ts +2 -1
- package/test/sep7.test.ts +219 -2
- package/test/server.test.ts +39 -0
- package/test/stellar.test.ts +35 -15
- package/test/transaction.test.ts +43 -0
- package/test/wallet.test.ts +2 -1
package/test/sep7.test.ts
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Account,
|
|
3
|
+
Address,
|
|
3
4
|
Asset,
|
|
4
5
|
BASE_FEE,
|
|
5
6
|
Keypair,
|
|
6
7
|
Networks,
|
|
7
8
|
Operation,
|
|
8
9
|
StellarToml,
|
|
10
|
+
Transaction,
|
|
9
11
|
TransactionBuilder,
|
|
12
|
+
nativeToScVal,
|
|
13
|
+
rpc,
|
|
14
|
+
xdr,
|
|
10
15
|
} from "@stellar/stellar-sdk";
|
|
11
16
|
import {
|
|
12
17
|
NativeAssetId,
|
|
@@ -25,9 +30,19 @@ import {
|
|
|
25
30
|
URI_REPLACE_MAX_LENGTH,
|
|
26
31
|
} from "../src/walletSdk/Types";
|
|
27
32
|
import {
|
|
33
|
+
Sep7ContractMemoError,
|
|
28
34
|
Sep7InvalidUriError,
|
|
29
35
|
Sep7LongMsgError,
|
|
30
36
|
} from "../src/walletSdk/Exceptions";
|
|
37
|
+
import {
|
|
38
|
+
MUXED_CONTRACT_BAD_CHECKSUM,
|
|
39
|
+
MUXED_CONTRACT_MAX_ID,
|
|
40
|
+
SEP23_CONTRACT,
|
|
41
|
+
SEP23_MUXED_CONTRACT,
|
|
42
|
+
TESTNET_NATIVE_SAC,
|
|
43
|
+
TRANSFER_TO_MUXED_CONTRACT_XDR,
|
|
44
|
+
transferRecipient,
|
|
45
|
+
} from "./fixtures/muxedContract";
|
|
31
46
|
|
|
32
47
|
const testKp1 = SigningKeypair.fromSecret(
|
|
33
48
|
"SBKQDF56C5VY2YQTNQFGY7HM6R3V6QKDUEDXZQUCPQOP2EBZWG2QJ2JL",
|
|
@@ -700,7 +715,14 @@ describe("sep7Parser", () => {
|
|
|
700
715
|
// With Soroban Contract destination
|
|
701
716
|
expect(
|
|
702
717
|
isValidSep7Uri(
|
|
703
|
-
"web+stellar:pay?destination=CAPECFLUT6KHYOOWUQNP7KC6PTMICKANBURFWRMPZTXUEEKHN67B7UI2&amount=120.1234567&
|
|
718
|
+
"web+stellar:pay?destination=CAPECFLUT6KHYOOWUQNP7KC6PTMICKANBURFWRMPZTXUEEKHN67B7UI2&amount=120.1234567&msg=pay%20me%20with%20lumens",
|
|
719
|
+
).result,
|
|
720
|
+
).toBe(true);
|
|
721
|
+
|
|
722
|
+
// With Muxed Contract destination
|
|
723
|
+
expect(
|
|
724
|
+
isValidSep7Uri(
|
|
725
|
+
`web+stellar:pay?destination=${SEP23_MUXED_CONTRACT}&amount=120.1234567&msg=pay%20me%20with%20lumens`,
|
|
704
726
|
).result,
|
|
705
727
|
).toBe(true);
|
|
706
728
|
});
|
|
@@ -857,7 +879,14 @@ describe("sep7Parser", () => {
|
|
|
857
879
|
// With Soroban Contract destination
|
|
858
880
|
expect(
|
|
859
881
|
parseSep7Uri(
|
|
860
|
-
"web+stellar:pay?destination=CAPECFLUT6KHYOOWUQNP7KC6PTMICKANBURFWRMPZTXUEEKHN67B7UI2&amount=120.123&asset_code=USD&asset_issuer=GCRCUE2C5TBNIPYHMEP7NK5RWTT2WBSZ75CMARH7GDOHDDCQH3XANFOB&
|
|
882
|
+
"web+stellar:pay?destination=CAPECFLUT6KHYOOWUQNP7KC6PTMICKANBURFWRMPZTXUEEKHN67B7UI2&amount=120.123&asset_code=USD&asset_issuer=GCRCUE2C5TBNIPYHMEP7NK5RWTT2WBSZ75CMARH7GDOHDDCQH3XANFOB&callback=url%3Ahttps%3A%2F%2FsomeSigningService.com%2Fhasysda987fs%3Fasset%3DUSD",
|
|
883
|
+
),
|
|
884
|
+
).toBeInstanceOf(Sep7Pay);
|
|
885
|
+
|
|
886
|
+
// With Muxed Contract destination
|
|
887
|
+
expect(
|
|
888
|
+
parseSep7Uri(
|
|
889
|
+
`web+stellar:pay?destination=${SEP23_MUXED_CONTRACT}&amount=120.123&asset_code=USD&asset_issuer=GCRCUE2C5TBNIPYHMEP7NK5RWTT2WBSZ75CMARH7GDOHDDCQH3XANFOB&callback=url%3Ahttps%3A%2F%2FsomeSigningService.com%2Fhasysda987fs%3Fasset%3DUSD`,
|
|
861
890
|
),
|
|
862
891
|
).toBeInstanceOf(Sep7Pay);
|
|
863
892
|
});
|
|
@@ -1067,3 +1096,191 @@ describe("SEP-7 byte encoding regressions", () => {
|
|
|
1067
1096
|
expect(uri.getTransaction().toXdr()).toEqual(tx.toXdr());
|
|
1068
1097
|
});
|
|
1069
1098
|
});
|
|
1099
|
+
|
|
1100
|
+
describe("SEP-7 with muxed contract (W) addresses", () => {
|
|
1101
|
+
it.each([
|
|
1102
|
+
["mux ID 0", SEP23_MUXED_CONTRACT],
|
|
1103
|
+
["the largest mux ID", MUXED_CONTRACT_MAX_ID],
|
|
1104
|
+
])(
|
|
1105
|
+
"parses a 'pay' uri to a W address with %s and keeps the address as given",
|
|
1106
|
+
(_, destination) => {
|
|
1107
|
+
const uri = parseSep7Uri(
|
|
1108
|
+
`web+stellar:pay?destination=${destination}&amount=10&asset_code=USDC&asset_issuer=GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5`,
|
|
1109
|
+
);
|
|
1110
|
+
|
|
1111
|
+
expect(uri).toBeInstanceOf(Sep7Pay);
|
|
1112
|
+
expect((uri as Sep7Pay).destination).toBe(destination);
|
|
1113
|
+
},
|
|
1114
|
+
);
|
|
1115
|
+
|
|
1116
|
+
it("rejects a 'pay' uri to a W address whose checksum doesn't match", () => {
|
|
1117
|
+
expect(
|
|
1118
|
+
isValidSep7Uri(
|
|
1119
|
+
`web+stellar:pay?destination=${MUXED_CONTRACT_BAD_CHECKSUM}&amount=10`,
|
|
1120
|
+
),
|
|
1121
|
+
).toEqual({
|
|
1122
|
+
result: false,
|
|
1123
|
+
reason:
|
|
1124
|
+
"the provided 'destination' parameter is not a valid Stellar address",
|
|
1125
|
+
});
|
|
1126
|
+
});
|
|
1127
|
+
|
|
1128
|
+
it("parses a 'tx' uri whose transaction pays a W address", () => {
|
|
1129
|
+
const uri = `web+stellar:tx?xdr=${encodeURIComponent(
|
|
1130
|
+
TRANSFER_TO_MUXED_CONTRACT_XDR,
|
|
1131
|
+
)}&network_passphrase=${encodeURIComponent(Networks.TESTNET)}`;
|
|
1132
|
+
|
|
1133
|
+
expect(isValidSep7Uri(uri)).toEqual({ result: true });
|
|
1134
|
+
|
|
1135
|
+
const tx = (parseSep7Uri(uri) as Sep7Tx).getTransaction();
|
|
1136
|
+
expect(transferRecipient(tx)).toBe(MUXED_CONTRACT_MAX_ID);
|
|
1137
|
+
expect(tx.toXdr()).toBe(TRANSFER_TO_MUXED_CONTRACT_XDR);
|
|
1138
|
+
});
|
|
1139
|
+
});
|
|
1140
|
+
|
|
1141
|
+
// Runs on testnet, which needs Protocol 30 for a W address to go on chain. A
|
|
1142
|
+
// dapp builds the transfer, has RPC add its Soroban data and passes it to a
|
|
1143
|
+
// wallet as a 'tx' uri, which the wallet signs and submits.
|
|
1144
|
+
describe("SEP-7 'tx' uri for a transfer to a W address, on testnet", () => {
|
|
1145
|
+
it("is signed and submitted by a wallet, and the network keeps the W", async () => {
|
|
1146
|
+
const stellar = Wallet.TestNet().stellar();
|
|
1147
|
+
const sourceKp = stellar.account().createKeypair();
|
|
1148
|
+
await stellar.fundTestnetAccount(sourceKp.publicKey);
|
|
1149
|
+
|
|
1150
|
+
const txBuilder = await stellar.transaction({ sourceAddress: sourceKp });
|
|
1151
|
+
const transfer = txBuilder
|
|
1152
|
+
.addOperation(
|
|
1153
|
+
Operation.invokeContractFunction({
|
|
1154
|
+
contract: TESTNET_NATIVE_SAC,
|
|
1155
|
+
function: "transfer",
|
|
1156
|
+
args: [
|
|
1157
|
+
new Address(sourceKp.publicKey).toScVal(),
|
|
1158
|
+
new Address(MUXED_CONTRACT_MAX_ID).toScVal(),
|
|
1159
|
+
nativeToScVal(12345, { type: "i128" }),
|
|
1160
|
+
],
|
|
1161
|
+
}),
|
|
1162
|
+
)
|
|
1163
|
+
.build();
|
|
1164
|
+
const prepared = await new rpc.Server(
|
|
1165
|
+
"https://soroban-testnet.stellar.org",
|
|
1166
|
+
).prepareTransaction(transfer);
|
|
1167
|
+
const uri = Sep7Tx.forTransaction(prepared).toString();
|
|
1168
|
+
|
|
1169
|
+
expect(isValidSep7Uri(uri)).toEqual({ result: true });
|
|
1170
|
+
const tx = (parseSep7Uri(uri) as Sep7Tx).getTransaction();
|
|
1171
|
+
expect(transferRecipient(tx)).toBe(MUXED_CONTRACT_MAX_ID);
|
|
1172
|
+
|
|
1173
|
+
sourceKp.sign(tx);
|
|
1174
|
+
expect(await stellar.submitTransaction(tx)).toBe(true);
|
|
1175
|
+
|
|
1176
|
+
const record = await stellar.server
|
|
1177
|
+
.transactions()
|
|
1178
|
+
.transaction(xdr.encodeBytes(tx.hash(), "hex"))
|
|
1179
|
+
.call();
|
|
1180
|
+
const onChain = stellar.decodeTransaction(
|
|
1181
|
+
record.envelope_xdr,
|
|
1182
|
+
) as Transaction;
|
|
1183
|
+
expect(transferRecipient(onChain)).toBe(MUXED_CONTRACT_MAX_ID);
|
|
1184
|
+
}, 60000);
|
|
1185
|
+
});
|
|
1186
|
+
|
|
1187
|
+
// A C or W address can only be paid with a Stellar Asset Contract transfer, and
|
|
1188
|
+
// that's a Soroban transaction, which can't carry a memo.
|
|
1189
|
+
describe("SEP-7 'pay' to a contract (C or W) address with a memo", () => {
|
|
1190
|
+
it.each([
|
|
1191
|
+
["C", "a MEMO_TEXT", SEP23_CONTRACT, "&memo=skdjfasf&memo_type=MEMO_TEXT"],
|
|
1192
|
+
["C", "a MEMO_ID", SEP23_CONTRACT, "&memo=1234&memo_type=MEMO_ID"],
|
|
1193
|
+
["C", "an untyped", SEP23_CONTRACT, "&memo=skdjfasf"],
|
|
1194
|
+
[
|
|
1195
|
+
"W",
|
|
1196
|
+
"a MEMO_TEXT",
|
|
1197
|
+
SEP23_MUXED_CONTRACT,
|
|
1198
|
+
"&memo=skdjfasf&memo_type=MEMO_TEXT",
|
|
1199
|
+
],
|
|
1200
|
+
["W", "a MEMO_ID", SEP23_MUXED_CONTRACT, "&memo=1234&memo_type=MEMO_ID"],
|
|
1201
|
+
["W", "an untyped", SEP23_MUXED_CONTRACT, "&memo=skdjfasf"],
|
|
1202
|
+
])(
|
|
1203
|
+
"rejects a 'pay' uri to a %s address that has %s memo",
|
|
1204
|
+
(_, __, destination, memoParams) => {
|
|
1205
|
+
const uri = `web+stellar:pay?destination=${destination}&amount=10${memoParams}`;
|
|
1206
|
+
|
|
1207
|
+
expect(isValidSep7Uri(uri)).toEqual({
|
|
1208
|
+
result: false,
|
|
1209
|
+
reason:
|
|
1210
|
+
"the 'memo' parameter is not supported for a contract ('C') or muxed contract ('W') 'destination'",
|
|
1211
|
+
});
|
|
1212
|
+
expect(() => parseSep7Uri(uri)).toThrow(Sep7InvalidUriError);
|
|
1213
|
+
},
|
|
1214
|
+
);
|
|
1215
|
+
});
|
|
1216
|
+
|
|
1217
|
+
// Sep7Pay shouldn't build a uri that parseSep7Uri rejects.
|
|
1218
|
+
describe("Sep7Pay with a memo and a contract (C or W) destination", () => {
|
|
1219
|
+
const ACCOUNT = "GCALNQQBXAPZ2WIRSDDBMSTAKCUH5SG6U76YBFLQLIXJTF7FE5AX7AOO";
|
|
1220
|
+
const MUXED_ACCOUNT =
|
|
1221
|
+
"MA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJUAAAAAAAAAABUTGI4";
|
|
1222
|
+
|
|
1223
|
+
describe.each([
|
|
1224
|
+
["C", SEP23_CONTRACT],
|
|
1225
|
+
["W", SEP23_MUXED_CONTRACT],
|
|
1226
|
+
])("to a %s address", (_, destination) => {
|
|
1227
|
+
it("the memo setter throws and leaves the uri unchanged", () => {
|
|
1228
|
+
const uri = Sep7Pay.forDestination(destination);
|
|
1229
|
+
|
|
1230
|
+
expect(() => {
|
|
1231
|
+
uri.memo = "skdjfasf";
|
|
1232
|
+
}).toThrow(Sep7ContractMemoError);
|
|
1233
|
+
expect(uri.toString()).toBe(`web+stellar:pay?destination=${destination}`);
|
|
1234
|
+
});
|
|
1235
|
+
|
|
1236
|
+
it("the destination setter throws on a uri that has a memo and leaves it unchanged", () => {
|
|
1237
|
+
const uri = Sep7Pay.forDestination(ACCOUNT);
|
|
1238
|
+
uri.memo = "skdjfasf";
|
|
1239
|
+
|
|
1240
|
+
expect(() => {
|
|
1241
|
+
uri.destination = destination;
|
|
1242
|
+
}).toThrow(Sep7ContractMemoError);
|
|
1243
|
+
expect(uri.toString()).toBe(
|
|
1244
|
+
`web+stellar:pay?destination=${ACCOUNT}&memo=skdjfasf`,
|
|
1245
|
+
);
|
|
1246
|
+
});
|
|
1247
|
+
|
|
1248
|
+
it("the constructor throws on a uri that has a memo", () => {
|
|
1249
|
+
expect(
|
|
1250
|
+
() =>
|
|
1251
|
+
new Sep7Pay(
|
|
1252
|
+
`web+stellar:pay?destination=${destination}&memo=skdjfasf`,
|
|
1253
|
+
),
|
|
1254
|
+
).toThrow(Sep7ContractMemoError);
|
|
1255
|
+
});
|
|
1256
|
+
|
|
1257
|
+
it("builds a uri that parses once the memo is cleared", () => {
|
|
1258
|
+
const uri = Sep7Pay.forDestination(ACCOUNT);
|
|
1259
|
+
uri.memo = "skdjfasf";
|
|
1260
|
+
uri.memo = undefined;
|
|
1261
|
+
uri.destination = destination;
|
|
1262
|
+
uri.amount = "10";
|
|
1263
|
+
|
|
1264
|
+
expect(() => {
|
|
1265
|
+
uri.memo = undefined;
|
|
1266
|
+
}).not.toThrow();
|
|
1267
|
+
expect(uri.toString()).toBe(
|
|
1268
|
+
`web+stellar:pay?destination=${destination}&amount=10`,
|
|
1269
|
+
);
|
|
1270
|
+
expect(parseSep7Uri(uri.toString())).toBeInstanceOf(Sep7Pay);
|
|
1271
|
+
});
|
|
1272
|
+
});
|
|
1273
|
+
|
|
1274
|
+
it.each([
|
|
1275
|
+
["G", ACCOUNT],
|
|
1276
|
+
["M", MUXED_ACCOUNT],
|
|
1277
|
+
])("the memo setter accepts a %s destination", (_, destination) => {
|
|
1278
|
+
const uri = Sep7Pay.forDestination(destination);
|
|
1279
|
+
uri.memo = "skdjfasf";
|
|
1280
|
+
|
|
1281
|
+
expect(uri.toString()).toBe(
|
|
1282
|
+
`web+stellar:pay?destination=${destination}&memo=skdjfasf`,
|
|
1283
|
+
);
|
|
1284
|
+
expect(parseSep7Uri(uri.toString())).toBeInstanceOf(Sep7Pay);
|
|
1285
|
+
});
|
|
1286
|
+
});
|
package/test/server.test.ts
CHANGED
|
@@ -277,6 +277,45 @@ describe("signChallengeTransaction validation", () => {
|
|
|
277
277
|
).rejects.toThrow(ChallengeValidationFailedError);
|
|
278
278
|
});
|
|
279
279
|
|
|
280
|
+
// WebAuth.readChallengeTx checks these since stellar-sdk 17.3. SEP-10
|
|
281
|
+
// requires the client_domain operation's source to be the client domain's
|
|
282
|
+
// signing key.
|
|
283
|
+
it.each([
|
|
284
|
+
["has no source account", "none"],
|
|
285
|
+
["uses the server account as its source", "server"],
|
|
286
|
+
])(
|
|
287
|
+
"should reject a challenge whose client_domain operation %s",
|
|
288
|
+
async (_, clientDomainSource) => {
|
|
289
|
+
const challenge = TransactionBuilder.cloneFrom(
|
|
290
|
+
TransactionBuilder.fromXDR(
|
|
291
|
+
buildChallenge(anchorAKp, anchorA, accountKp.publicKey),
|
|
292
|
+
networkPassphrase,
|
|
293
|
+
) as Transaction,
|
|
294
|
+
)
|
|
295
|
+
.addOperation(
|
|
296
|
+
Operation.manageData({
|
|
297
|
+
name: "client_domain",
|
|
298
|
+
value: "wallet.example.com",
|
|
299
|
+
source:
|
|
300
|
+
clientDomainSource === "server"
|
|
301
|
+
? anchorAKp.publicKey()
|
|
302
|
+
: undefined,
|
|
303
|
+
}),
|
|
304
|
+
)
|
|
305
|
+
.build();
|
|
306
|
+
challenge.sign(anchorAKp);
|
|
307
|
+
|
|
308
|
+
const result = Server.signChallengeTransaction({
|
|
309
|
+
accountKp,
|
|
310
|
+
challengeTx: challenge.toXDR(),
|
|
311
|
+
networkPassphrase,
|
|
312
|
+
anchorDomain: anchorA,
|
|
313
|
+
});
|
|
314
|
+
await expect(result).rejects.toThrow(ChallengeValidationFailedError);
|
|
315
|
+
await expect(result).rejects.toThrow(/client_domain/);
|
|
316
|
+
},
|
|
317
|
+
);
|
|
318
|
+
|
|
280
319
|
it("should accept an explicit homeDomain that differs from anchorDomain", async () => {
|
|
281
320
|
const homeDomain = "wallet-home.example.com";
|
|
282
321
|
const challengeTx = buildChallenge(
|
package/test/stellar.test.ts
CHANGED
|
@@ -21,6 +21,11 @@ import {
|
|
|
21
21
|
Assets,
|
|
22
22
|
} from "../src/walletSdk/Asset";
|
|
23
23
|
import { TransactionStatus, WithdrawTransaction } from "../src/walletSdk/Types";
|
|
24
|
+
import {
|
|
25
|
+
MUXED_CONTRACT_MAX_ID,
|
|
26
|
+
TRANSFER_TO_MUXED_CONTRACT_XDR,
|
|
27
|
+
transferRecipient,
|
|
28
|
+
} from "./fixtures/muxedContract";
|
|
24
29
|
import {
|
|
25
30
|
TransactionSubmitWithFeeIncreaseFailedError,
|
|
26
31
|
WithdrawalTxMemoError,
|
|
@@ -496,6 +501,8 @@ let txnSourceKp;
|
|
|
496
501
|
let sponsorKp;
|
|
497
502
|
let newKp;
|
|
498
503
|
describe("SponsoringBuilder", () => {
|
|
504
|
+
// One friendbot call can take 25 s or more on testnet, so this funds both
|
|
505
|
+
// accounts in parallel and allows 90 s.
|
|
499
506
|
beforeAll(async () => {
|
|
500
507
|
wal = Wallet.TestNet();
|
|
501
508
|
stellar = wal.stellar();
|
|
@@ -503,13 +510,11 @@ describe("SponsoringBuilder", () => {
|
|
|
503
510
|
txnSourceKp = new SigningKeypair(Keypair.random());
|
|
504
511
|
sponsorKp = new SigningKeypair(Keypair.random());
|
|
505
512
|
newKp = new SigningKeypair(Keypair.random());
|
|
506
|
-
await
|
|
507
|
-
"https://friendbot.stellar.org/?addr=" + sponsorKp.publicKey,
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
);
|
|
512
|
-
}, 30000);
|
|
513
|
+
await Promise.all([
|
|
514
|
+
axios.get("https://friendbot.stellar.org/?addr=" + sponsorKp.publicKey),
|
|
515
|
+
axios.get("https://friendbot.stellar.org/?addr=" + txnSourceKp.publicKey),
|
|
516
|
+
]);
|
|
517
|
+
}, 90000);
|
|
513
518
|
|
|
514
519
|
it("should sponsor creating an account", async () => {
|
|
515
520
|
const wal = Wallet.TestNet();
|
|
@@ -644,6 +649,8 @@ describe("Asset", () => {
|
|
|
644
649
|
});
|
|
645
650
|
});
|
|
646
651
|
|
|
652
|
+
// These tests wait on testnet, where one friendbot call can take 25 s or more,
|
|
653
|
+
// so they fund their accounts in parallel and allow 90 s.
|
|
647
654
|
describe("Account Modifying", () => {
|
|
648
655
|
it("should modify account ", async () => {
|
|
649
656
|
const wallet = Wallet.TestNet();
|
|
@@ -651,10 +658,10 @@ describe("Account Modifying", () => {
|
|
|
651
658
|
|
|
652
659
|
const sourceKp = new SigningKeypair(Keypair.random());
|
|
653
660
|
const otherKp = new SigningKeypair(Keypair.random());
|
|
654
|
-
await
|
|
655
|
-
"https://friendbot.stellar.org/?addr=" + sourceKp.publicKey,
|
|
656
|
-
|
|
657
|
-
|
|
661
|
+
await Promise.all([
|
|
662
|
+
axios.get("https://friendbot.stellar.org/?addr=" + sourceKp.publicKey),
|
|
663
|
+
axios.get("https://friendbot.stellar.org/?addr=" + otherKp.publicKey),
|
|
664
|
+
]);
|
|
658
665
|
|
|
659
666
|
// Add account signer
|
|
660
667
|
let txBuilder = await stellar.transaction({
|
|
@@ -718,7 +725,7 @@ describe("Account Modifying", () => {
|
|
|
718
725
|
|
|
719
726
|
resp = await stellar.server.loadAccount(sourceKp.publicKey);
|
|
720
727
|
expect(resp.signers[0].weight).toBe(0);
|
|
721
|
-
},
|
|
728
|
+
}, 90000);
|
|
722
729
|
|
|
723
730
|
it("should merge account", async () => {
|
|
724
731
|
const wallet = Wallet.TestNet();
|
|
@@ -727,8 +734,10 @@ describe("Account Modifying", () => {
|
|
|
727
734
|
|
|
728
735
|
const accountKp = account.createKeypair();
|
|
729
736
|
const sourceKp = account.createKeypair();
|
|
730
|
-
await
|
|
731
|
-
|
|
737
|
+
await Promise.all([
|
|
738
|
+
stellar.fundTestnetAccount(accountKp.publicKey),
|
|
739
|
+
stellar.fundTestnetAccount(sourceKp.publicKey),
|
|
740
|
+
]);
|
|
732
741
|
|
|
733
742
|
const txBuilder = await stellar.transaction({
|
|
734
743
|
sourceAddress: accountKp,
|
|
@@ -753,7 +762,7 @@ describe("Account Modifying", () => {
|
|
|
753
762
|
expect(found).toBeFalsy();
|
|
754
763
|
const accResp = await stellar.server.loadAccount(accountKp.publicKey);
|
|
755
764
|
expect(parseInt(accResp.balances[0].balance)).toBeGreaterThan(19998);
|
|
756
|
-
},
|
|
765
|
+
}, 90000);
|
|
757
766
|
});
|
|
758
767
|
|
|
759
768
|
// Hermetic (no network): stellar-sdk v16 tightened Memo validation, so a
|
|
@@ -818,3 +827,14 @@ describe("transferWithdrawalTransaction memo validation", () => {
|
|
|
818
827
|
).toThrow(WithdrawalTxMemoError);
|
|
819
828
|
});
|
|
820
829
|
});
|
|
830
|
+
|
|
831
|
+
describe("decodeTransaction with a muxed contract (W) address", () => {
|
|
832
|
+
it("decodes a transfer to a W address and re-encodes it unchanged", () => {
|
|
833
|
+
const tx = Wallet.TestNet()
|
|
834
|
+
.stellar()
|
|
835
|
+
.decodeTransaction(TRANSFER_TO_MUXED_CONTRACT_XDR) as Transaction;
|
|
836
|
+
|
|
837
|
+
expect(transferRecipient(tx)).toBe(MUXED_CONTRACT_MAX_ID);
|
|
838
|
+
expect(tx.toXdr()).toBe(TRANSFER_TO_MUXED_CONTRACT_XDR);
|
|
839
|
+
});
|
|
840
|
+
});
|
package/test/transaction.test.ts
CHANGED
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
} from "../src";
|
|
20
20
|
import { IssuedAssetId, NativeAssetId } from "../src/walletSdk/Asset";
|
|
21
21
|
import { PathPayBoundRequiredError } from "../src/walletSdk/Exceptions";
|
|
22
|
+
import { MUXED_CONTRACT_MAX_ID } from "./fixtures/muxedContract";
|
|
22
23
|
|
|
23
24
|
describe("Muxed Transactions", () => {
|
|
24
25
|
let wallet: Wallet;
|
|
@@ -424,3 +425,45 @@ describe("Path Payment bounds", () => {
|
|
|
424
425
|
expect(op.destMin).toBe("0.9000000");
|
|
425
426
|
});
|
|
426
427
|
});
|
|
428
|
+
|
|
429
|
+
// A muxed contract (W) address can only receive a Stellar Asset Contract
|
|
430
|
+
// transfer, so no classic operation may take one as its destination.
|
|
431
|
+
describe("classic operations to a muxed contract (W) address", () => {
|
|
432
|
+
const newBuilder = () =>
|
|
433
|
+
new TransactionBuilder(
|
|
434
|
+
new Config({
|
|
435
|
+
stellarConfiguration: StellarConfiguration.TestNet(),
|
|
436
|
+
applicationConfiguration: new ApplicationConfiguration(),
|
|
437
|
+
}),
|
|
438
|
+
new Account(Keypair.random().publicKey(), "0"),
|
|
439
|
+
);
|
|
440
|
+
|
|
441
|
+
it.each([
|
|
442
|
+
[
|
|
443
|
+
"transfer",
|
|
444
|
+
(builder: TransactionBuilder) =>
|
|
445
|
+
builder.transfer(MUXED_CONTRACT_MAX_ID, new NativeAssetId(), "1"),
|
|
446
|
+
],
|
|
447
|
+
[
|
|
448
|
+
"pathPay",
|
|
449
|
+
(builder: TransactionBuilder) =>
|
|
450
|
+
builder.pathPay({
|
|
451
|
+
destinationAddress: MUXED_CONTRACT_MAX_ID,
|
|
452
|
+
sendAsset: new NativeAssetId(),
|
|
453
|
+
destAsset: new IssuedAssetId(
|
|
454
|
+
"USDC",
|
|
455
|
+
"GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5",
|
|
456
|
+
),
|
|
457
|
+
sendAmount: "5",
|
|
458
|
+
destMin: "4.9",
|
|
459
|
+
}),
|
|
460
|
+
],
|
|
461
|
+
[
|
|
462
|
+
"accountMerge",
|
|
463
|
+
(builder: TransactionBuilder) =>
|
|
464
|
+
builder.accountMerge(MUXED_CONTRACT_MAX_ID),
|
|
465
|
+
],
|
|
466
|
+
])("%s refuses a W destination", (_, addOperation) => {
|
|
467
|
+
expect(() => addOperation(newBuilder())).toThrow("destination is invalid");
|
|
468
|
+
});
|
|
469
|
+
});
|
package/test/wallet.test.ts
CHANGED
|
@@ -2033,6 +2033,7 @@ describe("AuthHeaderSigner", () => {
|
|
|
2033
2033
|
beforeAll(() => {
|
|
2034
2034
|
jest.resetAllMocks();
|
|
2035
2035
|
});
|
|
2036
|
+
// One friendbot call can take 25 s or more on testnet, so this allows 90 s.
|
|
2036
2037
|
it("full sep-10 auth using header token should work", async () => {
|
|
2037
2038
|
const wallet = Wallet.TestNet();
|
|
2038
2039
|
const accountKp = wallet.stellar().account().createKeypair();
|
|
@@ -2054,7 +2055,7 @@ describe("AuthHeaderSigner", () => {
|
|
|
2054
2055
|
});
|
|
2055
2056
|
|
|
2056
2057
|
expect(authToken).toBeTruthy();
|
|
2057
|
-
},
|
|
2058
|
+
}, 90000);
|
|
2058
2059
|
|
|
2059
2060
|
it("should match example implementation generated JWT", async () => {
|
|
2060
2061
|
const generatedAuthToken =
|