|
1 | 1 | const merge = require("deepmerge")
|
2 | 2 |
|
3 |
| -import {encodeTransactionPayload, encodeTransactionEnvelope} from "./encode.js" |
| 3 | +import {encodeTransactionPayload, encodeTransactionEnvelope, encodeTxIdFromVoucher} from "./encode.js" |
4 | 4 | import * as root from "./encode.js"
|
5 | 5 |
|
6 | 6 | it("export contract interface", () => {
|
7 | 7 | expect(root).toStrictEqual(
|
8 | 8 | expect.objectContaining({
|
9 | 9 | encodeTransactionPayload: expect.any(Function),
|
10 | 10 | encodeTransactionEnvelope: expect.any(Function),
|
| 11 | + encodeTxIdFromVoucher: expect.any(Function), |
11 | 12 | })
|
12 | 13 | )
|
13 | 14 | })
|
@@ -241,3 +242,194 @@ describe("encode transaction", () => {
|
241 | 242 | })
|
242 | 243 | })
|
243 | 244 | })
|
| 245 | + |
| 246 | +const baseVoucher = { |
| 247 | + cadence: `transaction { execute { log("Hello, World!") } }`, |
| 248 | + arguments: [], |
| 249 | + refBlock: "f0e4c2f76c58916ec258f246851bea091d14d4247a2fc3e18694461b1816e13b", |
| 250 | + computeLimit: 42, |
| 251 | + proposalKey: { |
| 252 | + address: "01", |
| 253 | + keyId: 4, |
| 254 | + sequenceNum: 10, |
| 255 | + }, |
| 256 | + payer: "01", |
| 257 | + authorizers: ["01"], |
| 258 | + payloadSigs: [ |
| 259 | + { |
| 260 | + address: "01", |
| 261 | + keyId: 4, |
| 262 | + sig: "f7225388c1d69d57e6251c9fda50cbbf9e05131e5adb81e5aa0422402f048162", |
| 263 | + }, |
| 264 | + ], |
| 265 | + envelopeSigs: [], |
| 266 | +} |
| 267 | + |
| 268 | +const buildVoucher = partialVoucher => |
| 269 | + merge(baseVoucher, partialVoucher, {arrayMerge: combineMerge}) |
| 270 | + |
| 271 | +describe("encode txId from voucher", () => { |
| 272 | + const invalidPayloadCases = [ |
| 273 | + ["empty", {}], |
| 274 | + ["non-object", "foo"], |
| 275 | + |
| 276 | + ["null cadence", buildVoucher({cadence: null})], |
| 277 | + ["null computeLimit", buildVoucher({computeLimit: null})], |
| 278 | + ["null proposalKey", buildVoucher({proposalKey: null})], |
| 279 | + ["null proposalKey.address", buildVoucher({proposalKey: {address: null}})], |
| 280 | + ["null proposalKey.keyId", buildVoucher({proposalKey: {keyId: null}})], |
| 281 | + [ |
| 282 | + "null proposalKey.sequenceNum", |
| 283 | + buildVoucher({proposalKey: {sequenceNum: null}}), |
| 284 | + ], |
| 285 | + ["null payer", buildVoucher({payer: null})], |
| 286 | + ["null authorizers", buildVoucher({authorizers: null})], |
| 287 | + |
| 288 | + ["non-string cadence", buildVoucher({cadence: 42})], |
| 289 | + ["non-string refBlock", buildVoucher({refBlock: 42})], |
| 290 | + ["non-number computeLimit", buildVoucher({computeLimit: "foo"})], |
| 291 | + ["non-object proposalKey", buildVoucher({proposalKey: "foo"})], |
| 292 | + ["non-string proposalKey.address", buildVoucher({proposalKey: {address: 42}})], |
| 293 | + ["non-number proposalKey.keyId", buildVoucher({proposalKey: {keyId: "foo"}})], |
| 294 | + [ |
| 295 | + "non-number proposalKey.sequenceNum", |
| 296 | + buildVoucher({proposalKey: {sequenceNum: "foo"}}), |
| 297 | + ], |
| 298 | + ["non-string payer", buildVoucher({payer: 42})], |
| 299 | + ["non-array authorizers", buildVoucher({authorizers: {}})], |
| 300 | + ] |
| 301 | + |
| 302 | + const invalidPayloadSigsCases = [ |
| 303 | + ["null payloadSigs", buildVoucher({payloadSigs: null})], |
| 304 | + ["null payloadSigs.0.address", buildVoucher({payloadSigs: [{address: null}]})], |
| 305 | + ["null payloadSigs.0.keyId", buildVoucher({payloadSigs: [{keyId: null}]})], |
| 306 | + ["null payloadSigs.0.sig", buildVoucher({payloadSigs: [{sig: null}]})], |
| 307 | + |
| 308 | + ["non-array payloadSigs", buildVoucher({payloadSigs: {}})], |
| 309 | + [ |
| 310 | + "non-string payloadSigs.0.address", |
| 311 | + buildVoucher({payloadSigs: [{address: 42}]}), |
| 312 | + ], |
| 313 | + [ |
| 314 | + "non-number payloadSigs.0.keyId", |
| 315 | + buildVoucher({payloadSigs: [{keyId: "foo"}]}), |
| 316 | + ], |
| 317 | + ["non-string payloadSigs.0.sig", buildVoucher({payloadSigs: [{sig: 42}]})], |
| 318 | + ] |
| 319 | + |
| 320 | + const invalidEnvelopeSigsCases = [ |
| 321 | + ["null envelopeSigs", buildVoucher({envelopeSigs: null})], |
| 322 | + ["null envelopeSigs.0.address", buildVoucher({envelopeSigs: [{address: null}]})], |
| 323 | + ["null envelopeSigs.0.keyId", buildVoucher({envelopeSigs: [{keyId: null}]})], |
| 324 | + ["null envelopeSigs.0.sig", buildVoucher({envelopeSigs: [{sig: null}]})], |
| 325 | + |
| 326 | + ["non-array envelopeSigs", buildVoucher({envelopeSigs: {}})], |
| 327 | + [ |
| 328 | + "non-string envelopeSigs.0.address", |
| 329 | + buildVoucher({envelopeSigs: [{address: 42}]}), |
| 330 | + ], |
| 331 | + [ |
| 332 | + "non-number envelopeSigs.0.keyId", |
| 333 | + buildVoucher({envelopeSigs: [{keyId: "foo"}]}), |
| 334 | + ], |
| 335 | + ["non-string envelopeSigs.0.sig", buildVoucher({envelopeSigs: [{sig: 42}]})], |
| 336 | + ] |
| 337 | + |
| 338 | + // Test case format: |
| 339 | + // [ |
| 340 | + // <test name>, |
| 341 | + // <tx obj>, |
| 342 | + // <tx id>, // These values are calculated using Flow Go SDK test code. |
| 343 | + // ] |
| 344 | + const validCases = [ |
| 345 | + [ |
| 346 | + "complete tx", |
| 347 | + buildVoucher({}), |
| 348 | + "118d6462f1c4182501d56f04a0cd23cf685283194bb316dceeb215b353120b2b" |
| 349 | + ], |
| 350 | + [ |
| 351 | + "complete tx with envelope sig", |
| 352 | + buildVoucher({envelopeSigs: [{ address: "01", keyId: 4, sig: "f7225388c1d69d57e6251c9fda50cbbf9e05131e5adb81e5aa0422402f048162"}]}), |
| 353 | + "363172029cc6bfc5df3f99e84393e82b6c11e2a920c0e8c3229d077ae8bc31f7" |
| 354 | + ], |
| 355 | + [ |
| 356 | + "empty cadence", |
| 357 | + buildVoucher({cadence: ""}), |
| 358 | + "41dbbb83852ec8aa84dbeff03e29c0ed9c4a17b374eb0aa81695d83ccb344faf", |
| 359 | + ], |
| 360 | + [ |
| 361 | + "null refBlock", |
| 362 | + buildVoucher({refBlock: null}), |
| 363 | + "b01ac14da3e2a64e4c2e0a341ae2da832ff366b4c18b665fdd1fb5837e6128e0", |
| 364 | + ], |
| 365 | + [ |
| 366 | + "zero computeLimit", |
| 367 | + buildVoucher({computeLimit: 0}), |
| 368 | + "c149bf2077e174ccbf190f28eecda915f355333afb247f5c2ec44c2d041faf64", |
| 369 | + ], |
| 370 | + [ |
| 371 | + "zero proposalKey.key", |
| 372 | + buildVoucher({proposalKey: {keyId: 0}}), |
| 373 | + "1627bf4a626af55e0230b466b3828cb54822e53585f704e99a37abbbe6fbe51a", |
| 374 | + ], |
| 375 | + [ |
| 376 | + "zero proposalKey.sequenceNum", |
| 377 | + buildVoucher({proposalKey: {sequenceNum: 0}}), |
| 378 | + "3e9541ecee13b87a1c7be5e9ef0a00e4d48937a6f3df25167ffab2d4b4c846f4", |
| 379 | + ], |
| 380 | + [ |
| 381 | + "multiple authorizers", |
| 382 | + buildVoucher({authorizers: ["01", "02"]}), |
| 383 | + "6c4b45769cabadf30a103693195845ae633907f701cdcfa775bb830b6c80cb5b", |
| 384 | + ], |
| 385 | + [ |
| 386 | + "empty payloadSigs", |
| 387 | + buildVoucher({payloadSigs: []}), |
| 388 | + "c56b673a57fb94d546b9c30ac637d20021d04faf046e2cd5ea32591b7175794e" |
| 389 | + ], |
| 390 | + [ |
| 391 | + "out-of-order payloadSigs -- by signer", |
| 392 | + buildVoucher({ |
| 393 | + authorizers: ["01", "02", "03"], |
| 394 | + payloadSigs: [ |
| 395 | + {address: "03", keyId: 0, sig: "f7225388c1d69d57e6251c9fda50cbbf9e05131e5adb81e5aa0422402f048162"}, |
| 396 | + {address: "01", keyId: 0, sig: "f7225388c1d69d57e6251c9fda50cbbf9e05131e5adb81e5aa0422402f048162"}, |
| 397 | + {address: "02", keyId: 0, sig: "f7225388c1d69d57e6251c9fda50cbbf9e05131e5adb81e5aa0422402f048162"}, |
| 398 | + ], |
| 399 | + }), |
| 400 | + "b67576744b0d051ba81e4d6635a47b9c8973b3adc7410bcd213880d5094b264a" |
| 401 | + ], |
| 402 | + [ |
| 403 | + "out-of-order payloadSigs -- by key ID", |
| 404 | + buildVoucher({ |
| 405 | + authorizers: ["01"], |
| 406 | + payloadSigs: [ |
| 407 | + {address: "01", keyId: 2, sig: "f7225388c1d69d57e6251c9fda50cbbf9e05131e5adb81e5aa0422402f048162"}, |
| 408 | + {address: "01", keyId: 0, sig: "f7225388c1d69d57e6251c9fda50cbbf9e05131e5adb81e5aa0422402f048162"}, |
| 409 | + {address: "01", keyId: 1, sig: "f7225388c1d69d57e6251c9fda50cbbf9e05131e5adb81e5aa0422402f048162"}, |
| 410 | + ], |
| 411 | + }), |
| 412 | + "183a74ecc0782fbffc364cac0c404ee01144ae258841b806a6274259bfc7ef8b" |
| 413 | + ], |
| 414 | + ] |
| 415 | + |
| 416 | + describe("invalid", () => { |
| 417 | + test.each(invalidPayloadCases)("%s", (_, voucher) => { |
| 418 | + expect(() => encodeTxIdFromVoucher(voucher)).toThrow() |
| 419 | + }) |
| 420 | + |
| 421 | + test.each(invalidPayloadSigsCases)("%s", (_, voucher) => { |
| 422 | + expect(() => encodeTxIdFromVoucher(voucher)).toThrow() |
| 423 | + }) |
| 424 | + |
| 425 | + test.each(invalidEnvelopeSigsCases)("%s", (_, voucher) => { |
| 426 | + expect(() => encodeTxIdFromVoucher(voucher)).toThrow() |
| 427 | + }) |
| 428 | + }) |
| 429 | + |
| 430 | + describe("valid", () => { |
| 431 | + test.each(validCases)("%s", (_, voucher, expectedTxId) => { |
| 432 | + expect(encodeTxIdFromVoucher(voucher)).toBe(expectedTxId) |
| 433 | + }) |
| 434 | + }) |
| 435 | +}) |
0 commit comments