From 7a0a06ad51b8004d8e801d80df77b1fea2db226a Mon Sep 17 00:00:00 2001 From: Oliver He Date: Thu, 9 Jan 2025 04:37:34 +0700 Subject: [PATCH 1/2] Update the JWTs for the keyless tests (#614) --- tests/e2e/api/keyless.test.ts | 109 ++++++++++-------- tests/e2e/transaction/helper.ts | 2 +- .../transaction/transactionBuilder.test.ts | 2 +- 3 files changed, 64 insertions(+), 49 deletions(-) diff --git a/tests/e2e/api/keyless.test.ts b/tests/e2e/api/keyless.test.ts index c68bddbd4..022649fc7 100644 --- a/tests/e2e/api/keyless.test.ts +++ b/tests/e2e/api/keyless.test.ts @@ -2,56 +2,65 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -import { Account, FederatedKeylessAccount, Hex, KeylessAccount, ProofFetchStatus } from "../../../src"; +import { + Account, + FederatedKeylessAccount, + Groth16Zkp, + KeylessAccount, + ProofFetchStatus, + ZeroKnowledgeSig, + ZkProof, + ZkpVariant, +} from "../../../src"; import { FUND_AMOUNT, TRANSFER_AMOUNT } from "../../unit/helper"; import { getAptosClient } from "../helper"; import { EPHEMERAL_KEY_PAIR, simpleCoinTransactionHeler as simpleCoinTransactionHelper } from "../transaction/helper"; export const TEST_JWT_TOKENS = [ - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci0wIiwiZW1haWwiOiJ0ZXN0QGFwdG9zbGFicy5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiaWF0IjoxNzI1NDc1MTEyLCJleHAiOjI3MDAwMDAwMDAsIm5vbmNlIjoiNzA5NTI0MjMzMzk2NDQ1NzI2NzkzNDcyMzc2ODA4MDMwMzMyNDQ2MjgyMTE5MTc1NjQwOTQ1MDA5OTUxOTc4MTA1MTkxMDE4NzExOCJ9.eHqJLdje0FRD3UPmSw8sFHRYe9lwqSydAMcfHcpxkFwew2OTy6bWFsLQTdJp-eCZPhNzlfBXwNxaAJZksCWFWkzCz2913a5b88XRT9Im7JBDtA1e1IBXrnfXG0MDpsVRAuRNzLWqDi_4Fl1OELvoEOK-Tl4cmIwOhBr943S-b14PRVhrQ1XBD5MXaHWcJyxMaEtZfu_xxCQ-jjR---iguD243Ze98JlcOIV8VmEBg3YiSyVdMDZ8cgRia0DI8DwFn7rIxaV2H5FXb9JcehLgNP82-gsfEGV0iAXuBk7ZvRzMVA-srE9JvxVOyq5UkYu0Ss9LjKzX0KVojl7Au_OxGA", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci0xIiwiZW1haWwiOiJ0ZXN0QGFwdG9zbGFicy5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiaWF0IjoxNzI1NDc1MTEyLCJleHAiOjI3MDAwMDAwMDAsIm5vbmNlIjoiNzA5NTI0MjMzMzk2NDQ1NzI2NzkzNDcyMzc2ODA4MDMwMzMyNDQ2MjgyMTE5MTc1NjQwOTQ1MDA5OTUxOTc4MTA1MTkxMDE4NzExOCJ9.AS1NTZSzPf9Pzv-12mZ2ozKYf1XxlHGn58GpKpe9odFquQ9YHD3klnwN-dM93keSNL6K9MyPh33SBZ1mzWSRxhC2by_9qOf410QgmH27_CxJdy1w2oLaVMCL0JmQUB7IsMcrVr1SflV6hNeqDoRfGzwM4kl2ocutLoRcm2cm52s2aPBajb43qTIeuK3CoJwIS4tfU9LhiqofpQ_zeFpk4yv0YmYzoI8QT3cVQDxtli90g0_VtUtaIFiF63uJrGh0dpt8mISNGKccRnDEtb-DrdnEdGoQQFFLTwJQXG8dvcCPEkt1qbL7-iUZxW2h9oU4XnKK_1kxe63K2Lp0O3XbEg", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci0yIiwiZW1haWwiOiJ0ZXN0QGFwdG9zbGFicy5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiaWF0IjoxNzI1NDc1MTEyLCJleHAiOjI3MDAwMDAwMDAsIm5vbmNlIjoiNzA5NTI0MjMzMzk2NDQ1NzI2NzkzNDcyMzc2ODA4MDMwMzMyNDQ2MjgyMTE5MTc1NjQwOTQ1MDA5OTUxOTc4MTA1MTkxMDE4NzExOCJ9.IGxHuaxvNZTpxIU1YgPmJ8nA85xj21JpYELpIxMQPeoeX1Jd9LkpNp71GkSacI9GGzDjRzCCyVlP31EEHO321VwJt2cBDBIKN75cthxM3wJAirL3IkcvF4cOGRmYoIwJo94U2qtIrV2hsUkAFrzQBQeG8kw-_f1h9dFZOJwJ21YJK0jsocsKWxm3cMjpLFm6lbVfGBlZDFQlAPctf6FvVrdzQx-L3bNFrVaXd_ONlBzxur1hZVIgzvcqdc1vk7hcITGEAOu5Kl2fA-WobIobVBgJsiLUUTqHQjQpW2hARZWKF41nvRQzExVBjb2V5DemgEz5WYIqj6MPvsQNQos1vQ", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci0zIiwiZW1haWwiOiJ0ZXN0QGFwdG9zbGFicy5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiaWF0IjoxNzI1NDc1MTEyLCJleHAiOjI3MDAwMDAwMDAsIm5vbmNlIjoiNzA5NTI0MjMzMzk2NDQ1NzI2NzkzNDcyMzc2ODA4MDMwMzMyNDQ2MjgyMTE5MTc1NjQwOTQ1MDA5OTUxOTc4MTA1MTkxMDE4NzExOCJ9.pKTMY9nOVj3_XYCkLhrNIqXdxX5o5it8dtQQmmm8ct8utZJT1ILPtv7iXwLo8fMN4O8RQIfjqRC8DorQ1u7pwkrTB0yL4WsOGFBoeRrDes0cOrqv8ACqmcU3Xy0Gq_qyPNQ9lyOGOeaiW39GiybvxlxPVPvN4D_bL6JQTxjiqpkAWquXRtYu_IbmZ6Nlo_kNUX34vsd3xeeIKBNk06xBeMk0Euc5Cs5mipt7Vt8YeZG0EEHbmUFc4eG9-BKO4Zjsay7cXx8fCvKUXzdbGzPlWXVW-E4xoGJHFVmNfhbua2VJ6scz1GkWHUR-evnHlukPIAmmgMWcBlPfaqftDGMpew", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci00IiwiZW1haWwiOiJ0ZXN0QGFwdG9zbGFicy5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiaWF0IjoxNzI1NDc1MTEyLCJleHAiOjI3MDAwMDAwMDAsIm5vbmNlIjoiNzA5NTI0MjMzMzk2NDQ1NzI2NzkzNDcyMzc2ODA4MDMwMzMyNDQ2MjgyMTE5MTc1NjQwOTQ1MDA5OTUxOTc4MTA1MTkxMDE4NzExOCJ9.OmHSYoRgP8i8BCT7IbM8U4VxEwtW68VMYOoUmMVdDpG3fPeupPVBr1EzdeJtB3B0gMiyD6W2mPVvcohSJJFNQFIGlUNP4e9ge2_b5fuC3bgI8UdAMKblt7FotYpkqGxeU-DEErioto5MXTzSi1UwQH4zmxQ1hDIOgYScNfO2LyHMueKz67FzDgIUm470AFLmc8TBrWVPXEyYWFdtpDO5yl_yplbQEXf0Z0tYpnHTwYgijnxAsNZ-_lX7CdorXSBZSXtpXHjwCl5WJv8cC65oxQLqVIsqwwdWzvtnZEHpLeERVt7NHyLHu7zfh1lohtZ6ulkKAr0Aot0r8BF0evy8mg", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci01IiwiZW1haWwiOiJ0ZXN0QGFwdG9zbGFicy5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiaWF0IjoxNzI1NDc1MTEyLCJleHAiOjI3MDAwMDAwMDAsIm5vbmNlIjoiNzA5NTI0MjMzMzk2NDQ1NzI2NzkzNDcyMzc2ODA4MDMwMzMyNDQ2MjgyMTE5MTc1NjQwOTQ1MDA5OTUxOTc4MTA1MTkxMDE4NzExOCJ9.TbhkVpFaM3MTq1iAMNzI8ki0jX6PrtBmFkjASphGzlGdPBHVzwfbjTz0dEMXeKYAjggFJmhCinjsach5XYX0gQXIgIlb1xtde2xRxCe1SBZINmkCiJc7Bx19TXJnGNA74EBRwr6jEPGxhTMkrGRWXCedGKiuyc5Jg7znJTJ-pyc4cXV5YF6OWhQhx7voB9gotWECfnuumdx-AFq4C4Y3f3W30CvaqDBXNg0C9aRQvnDMTyQdbh82tJfMS59mrKUtOlloiyExtmKEyF0dr6io3JHN-Om8V5Wo72gDHTQWo4oqR3BfHXRzOcjPHZ34x6tj6nC9Kj3LHRmaZa-19nqvwA", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci02IiwiZW1haWwiOiJ0ZXN0QGFwdG9zbGFicy5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiaWF0IjoxNzI1NDc1MTEyLCJleHAiOjI3MDAwMDAwMDAsIm5vbmNlIjoiNzA5NTI0MjMzMzk2NDQ1NzI2NzkzNDcyMzc2ODA4MDMwMzMyNDQ2MjgyMTE5MTc1NjQwOTQ1MDA5OTUxOTc4MTA1MTkxMDE4NzExOCJ9.CVS5cqsXTFpkXBNxtk2ZDB2r6PeCpaT5MrqIBTulwx1p28dHZWe72Q0SdzRRc9oTWqk-u8yBYi_FY1v6A9YKGZHvXva80FmIWeOp4w4vnObOq_0TyDc6q-6_RO9h48WKy9fWlxhCFkTgzWbvBWKK2SsDDkQXRMTYO9PyIQgh40Npr5_S7p55kTanMroi7nAC-4zO5p_RnpwbUVxJwoECON5yJ_OiVI8PaGZCOiBErLB-rMxn88I7v3N4OCOMdom5WFNNM06dacFFy4JZ5JDrrL390BHEtZ0Q-lF0k8LzLpy3jIjSa0tnJOs5FTjgbT0wMGP8wpZPQE_1gPbCcyq7FQ", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci03IiwiZW1haWwiOiJ0ZXN0QGFwdG9zbGFicy5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiaWF0IjoxNzI1NDc1MTEyLCJleHAiOjI3MDAwMDAwMDAsIm5vbmNlIjoiNzA5NTI0MjMzMzk2NDQ1NzI2NzkzNDcyMzc2ODA4MDMwMzMyNDQ2MjgyMTE5MTc1NjQwOTQ1MDA5OTUxOTc4MTA1MTkxMDE4NzExOCJ9.tps0gbu7xegBEMKRGOjltzhv0Ifg_35V1onFfxH4byxbmfOf0hkTbUqrLjFj9ZX31gIP6GRew68MQ6aqyvV4gEb5itnRTHXINVOfjCeFBxQvl94mgnMO5bE1bztSpYLYT6o90Jz6ZC-jwExu3MBFJHCLrSfZy-zdQe_5onkE4RnLsHuesMI7BxSCLHfSQdy7ZoRRx1yhhwTjB-JSQuugBP4j9hC5Ep7lfvIt3JPJoXFdY_JdlgtfQnHNACRTzeOLZEHA_u906OusBioql0ocmEwcCLtvecu7h3Z-IFIugja1kmocJYDhgyvVp2mbcdXlTlA7eb0KhCpEi__IBRPxUw", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci04IiwiZW1haWwiOiJ0ZXN0QGFwdG9zbGFicy5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiaWF0IjoxNzI1NDc1MTEyLCJleHAiOjI3MDAwMDAwMDAsIm5vbmNlIjoiNzA5NTI0MjMzMzk2NDQ1NzI2NzkzNDcyMzc2ODA4MDMwMzMyNDQ2MjgyMTE5MTc1NjQwOTQ1MDA5OTUxOTc4MTA1MTkxMDE4NzExOCJ9.FBTeSMj5nunVsZcL-poKbcdrEBDfZpEkoPjg87fOHkrFIrQUHWX6SFpUxoY_t-OwJ7cAb85655ytGPGm4kIFKqJru8DMXwt6M5KG9ir8p8FXLsw-z2KJ7COaEItqnEIS4EHC_HTveluLdV66yZ4DfXEakFyZVhX89Ys3KQe_xMl73c2hPBQQHwieZJeuqkA2zEFhqlr-pLmqFeZm9onHITc4XIl_uFKw-F7zfUvxz5ix7pjjltVylxtjpjuW8Z29kC8PjoaneaJamuA8a8mjwZXOI7mg6c8EuLTCdmZfBZto183qHtmlaKm_1LCky80dfRAY3lSZw_9E8QseBscVfQ", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci05IiwiZW1haWwiOiJ0ZXN0QGFwdG9zbGFicy5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiaWF0IjoxNzI1NDc1MTEyLCJleHAiOjI3MDAwMDAwMDAsIm5vbmNlIjoiNzA5NTI0MjMzMzk2NDQ1NzI2NzkzNDcyMzc2ODA4MDMwMzMyNDQ2MjgyMTE5MTc1NjQwOTQ1MDA5OTUxOTc4MTA1MTkxMDE4NzExOCJ9.B3CubAPmu51Ysl7nlhYmGnzgJKjcF6H5A7D5pgjXCXvX7FWA7fwvar0y7TdSj7VSR45TLS5qLd0Iro9zfk_7rhRtNiRQYH5_SyOljCQCiIHs8FHCjZJlcCAqLILQbPinwFXe_LlSMekwAzgXd0ugPyPjSSwI32jkIkGHmif1zAfgWPw6FE6B3x4L_SMWublc4kOBsiGB4zQ2MiMlLK4alVoOatIVOJIC9Q2rGwDR-Pny4xIym6Z96Z1wZR_612RlUs52LSaHnCJn972fm1xhNMqlLhD_6BPP0U0vkrXfGI7PezfIEXDB2X6KLPgnasJcmvMWaPg7Hsrni4kapzGM2g", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci0xMCIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6MTcyNTQ3NTExMiwiZXhwIjoyNzAwMDAwMDAwLCJub25jZSI6IjcwOTUyNDIzMzM5NjQ0NTcyNjc5MzQ3MjM3NjgwODAzMDMzMjQ0NjI4MjExOTE3NTY0MDk0NTAwOTk1MTk3ODEwNTE5MTAxODcxMTgifQ.DqWxLChrjRx8oAAqmpaLdBia7td6KFnS3lcrZl4lglPUZG3PE6rOoNXHR0ldxOA8lARZ52eO-Ar7r8ElLp-aqHuU8CTjt_zWF8-w-BustE6Akdq6o_4Nbmd1fZuaU6qqgEMhtQU9MQhoKCkHom-KwDnlj9JXnDksppkQIjlxwxH2KSs3lSOCydZzS-YdWp9yeerMi9Boq3JqHe-yScUm-HgMIOfQWlDqTo7O9T-3xjboFbZ70xBjKA4qxolp3GA7ciILbe58MCK_cXbFswSDujFZhmujGcWDZ-jNDAKJvDICNYTIVlrgEY79N18ixfPVYykMakLtm_zoTCXu5VFQnQ", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci0xMSIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6MTcyNTQ3NTExMiwiZXhwIjoyNzAwMDAwMDAwLCJub25jZSI6IjcwOTUyNDIzMzM5NjQ0NTcyNjc5MzQ3MjM3NjgwODAzMDMzMjQ0NjI4MjExOTE3NTY0MDk0NTAwOTk1MTk3ODEwNTE5MTAxODcxMTgifQ.C2x-69mc-7OlDTy7cvjqqIy4BDkpysdEFudWbNvlDKBV6xzGNeBJu4suvMIGQ_OSz0s2fI1BDm4gzxgrSPLYBdnO4rAGOkboW6sgrYzVHYl56t-WPDY0w0vxjHx2fS7sl6W3OnrKNLOOThhHQRtF3zWt2B4yp-IgF-RZufeVnQJ6u5xZmSJGUeZIpt_LKiLP22vPXHWHu73MIFrjIC9JRi2gHiYt-3aXeHZ3f1OP7tfbGod8zS0-ObIpdxUF9LU8Py_UjgFzrGuJc9LCrGgoHfdP-qNwpQCsn6yEkT2eK4eD6FQwjiTZ8sD1a91JBs6AFjCo9VY8WobQgcx1mKb3SQ", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci0xMiIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6MTcyNTQ3NTExMiwiZXhwIjoyNzAwMDAwMDAwLCJub25jZSI6IjcwOTUyNDIzMzM5NjQ0NTcyNjc5MzQ3MjM3NjgwODAzMDMzMjQ0NjI4MjExOTE3NTY0MDk0NTAwOTk1MTk3ODEwNTE5MTAxODcxMTgifQ.DdBNljIxQ3kQC3uN34p5cq6GBM_u4UaVpMeB52DEA6BKJYP3kICDyk3pOWyb0dH87fXrbXA_jvxwlvH24kTusba28kVjwJKK2Jia7zGdTym07JZ8JkQwnFse-n5iuy3Hq9P_EUow3U5LkcBl1E0bQY4s08GCbDVImJQOfZmqnroGO8Bjoj3iOdTm9v_Pg9OTJQsZbJ7SNRdRkxH9BFe2i1lY1DXo9c-w85iTPsh6ZxFtSUx1aFtCUmwC-3bvG76zo8HHJzE5_1QV7Lov90yXMDJWTgNrJwxgUc0NarYE1SN9LqOhY4oUJPtDw2_erqFC2aWktwYg6ZtwB-QLKuYuIw", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci0xMyIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6MTcyNTQ3NTExMiwiZXhwIjoyNzAwMDAwMDAwLCJub25jZSI6IjcwOTUyNDIzMzM5NjQ0NTcyNjc5MzQ3MjM3NjgwODAzMDMzMjQ0NjI4MjExOTE3NTY0MDk0NTAwOTk1MTk3ODEwNTE5MTAxODcxMTgifQ.VybD_NpPN9k1YoP0pr-EBSzJh2cRTOjY8BiAagfMTAi0nWxN5IBsdggtUU8n8JTRs5fBoJzDU8CVER5rfPw0lVkSQDOc9FChsWkIj1V3920l8jzFDhPH3N-Fqmx5FWPVQqKmSemzJf0QP8liRo7QhPsjTdMlmhGuTHh3eEBaESnHaXuQt1TxFNsje5oRIp_4m1eJyGA4T_ySbmzwS0xj-LNZR-zZinTNcU1YzOZJeU3kolntoMfZtncxU7vBeomgN-STfRYhZKSEf5i4kWyz97x2K1NxaeyFt4X6RKRi8XKox1G-jTWccWNLNvk0vlj7Fe-02SSN5R9KeZDCvsST-A", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci0xNCIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6MTcyNTQ3NTExMiwiZXhwIjoyNzAwMDAwMDAwLCJub25jZSI6IjcwOTUyNDIzMzM5NjQ0NTcyNjc5MzQ3MjM3NjgwODAzMDMzMjQ0NjI4MjExOTE3NTY0MDk0NTAwOTk1MTk3ODEwNTE5MTAxODcxMTgifQ.ifgg8rjh_uClJAKUTEWIrkdZ3LNv8h1wR1YrRxx0VDPz6i-pq77BtC311gFAJDsMR5X2MDHAnbpxea4CxoRABKZV_et3erCyhNLCapWv-QgYjyvuGhFVQ9jzECs8k-FcTLRwYOZD85eOmpi7bBHCfd75kckdYjt82MjToMrY37dyFkSpu7XhcqMvyfpRSu6G4mwYtc9Wg_PJ1tDgxcyqhk2fh7MFZ4mlxbbHA90wR4-rdp57_Q9yVjNNetnQ3z90Uj7aFknEb256g0dkRORf7cjRqR20KuA6mRm7Yji7YlL1rBXPa_0OFmNl494fovQG07YWChSc6xmnNeDJUfQXvA", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci0xNSIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6MTcyNTQ3NTExMiwiZXhwIjoyNzAwMDAwMDAwLCJub25jZSI6IjcwOTUyNDIzMzM5NjQ0NTcyNjc5MzQ3MjM3NjgwODAzMDMzMjQ0NjI4MjExOTE3NTY0MDk0NTAwOTk1MTk3ODEwNTE5MTAxODcxMTgifQ.OQjh3upJbNjFPB85okrYl9v1-HAT0enr7i2UVc9tT0o489AZiTyLEWaoXXrdu0sx5nAqrt4FMdo1wxSn4UZbWs1TV2W5vz2EKDMLYxYnGlRriaoC98tWTUjCjowXsyhrmJOnedkl5pWyYn32vaXUT5Pb4RbapXw1EBV_wKkGdvjAWaOZs7yhZAycGVNJI90gHRG5hT009gr4jsi2nZU6MnaRtmRSzUS-J3Ky7yFX3rn2PnQ-_wOzQhy2a67doLTmCK5Wr0xj0PsNa2f5nYwwcxAmXMNdiUFYw85zyXwR-rGCvBGDZeZ21oFwlfjTcCJWGbOnXlUniHanpKOh4UkwPA", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci0xNiIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6MTcyNTQ3NTExMiwiZXhwIjoyNzAwMDAwMDAwLCJub25jZSI6IjcwOTUyNDIzMzM5NjQ0NTcyNjc5MzQ3MjM3NjgwODAzMDMzMjQ0NjI4MjExOTE3NTY0MDk0NTAwOTk1MTk3ODEwNTE5MTAxODcxMTgifQ.ToOnqSm2FMWOO1dIFEcJIhwb2HGUKWycwS_HRZ4Xa8BJy6KZWYI1Eo9kkvsOG-E_ZrlB6T7QzaYk2r3tEFzw6vXEFy5AbynRMh5wQjlE5YdlGMh2DHymgvYucWrVTTq2HZheifMv4rJUsNzKgtfJdk0u0kqKnel3RP9EP_8xpdWM6NdeQaLQ9uyHBQVYh_jqm_Pw7q9McMpUP2zea7pUIf8ZnOapNFekYVUWKDL-kwRfM23DJ0RzE_8PTGqbslRZMMFFxF4lRXR1kAtRKYqxw9tWlALTLNRNJz2V_puBp3UTJ0szNfr9J4x7iwkF-CPPYK4vGmDtSwxLW_7Et8n8KQ", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci0xNyIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6MTcyNTQ3NTExMiwiZXhwIjoyNzAwMDAwMDAwLCJub25jZSI6IjcwOTUyNDIzMzM5NjQ0NTcyNjc5MzQ3MjM3NjgwODAzMDMzMjQ0NjI4MjExOTE3NTY0MDk0NTAwOTk1MTk3ODEwNTE5MTAxODcxMTgifQ.DsuzT_799TsJLSR0D0HR9ozpiRMb-_Xm_5pTRbZ91AR6hlypvCnD_gM6bjcz_te8v8EoAYfrJkQPNmETTro_wzXzfxyFmP42ml2bPhtIM5Lpfa0nwHOIMiOnW9F3nsIaZcBL3WJG_h46RyIwaOfoDIAz2320Dn_N-wgoUOQbvC8lnpWf2w8FjkqcO2AWhpE6P6tZYGCgKyW8mJKgEv1WrrCNM37iqwkaMv2Mdk3ghERa8Mu-WEJcuOoZ0hSoy0SoLJIJjMja8SfMw27wZsPMQqwlCp-mNbBfbBa_EkLmVcVYZoPL6X6MF_gk2rCnZaqh54-lHEJCPMV0P0_T06N2tQ", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci0xOCIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6MTcyNTQ3NTExMiwiZXhwIjoyNzAwMDAwMDAwLCJub25jZSI6IjcwOTUyNDIzMzM5NjQ0NTcyNjc5MzQ3MjM3NjgwODAzMDMzMjQ0NjI4MjExOTE3NTY0MDk0NTAwOTk1MTk3ODEwNTE5MTAxODcxMTgifQ.sQjWTpenq4VJPq3kvCcJIIbTcZvOT64AgZ7yEMNHM2Nx5RHARzvnqfGwUOxEHzO0bwKNzEvVJR86D2QQnoUOPXK0QdeZuI1olhVof4i1gq3VeL9xi94mWSEgjnZorJCBma5I5djq2cbnIuMTCpHmvgLLIqZyZFJydcaBY9gQAFaFkD2DWfz3J38E-guuRwjV0G76gfiAU7mRNEkT1cZX57HxABJzrEMmri5wmY7dfErdwuqU5hLBzJiD5jPMy9QiZ_xjVnkSZ8NEtOXQjT9i69MHdnpnKxVSAqoMBHdplJgvNixgUnX3zoecHVlxPQInYNvATgtMMlSLOX1euKUykw", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci0xOSIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6MTcyNTQ3NTExMiwiZXhwIjoyNzAwMDAwMDAwLCJub25jZSI6IjcwOTUyNDIzMzM5NjQ0NTcyNjc5MzQ3MjM3NjgwODAzMDMzMjQ0NjI4MjExOTE3NTY0MDk0NTAwOTk1MTk3ODEwNTE5MTAxODcxMTgifQ.elbm8TQ1qHbxKmTPq0ShHiRNiqZ_bF_GG25Gjeb4JliYz4PTrxtocXX4Frez_4nf7mCbgcB37fkuJrcyHQ5QaCxjWrVzqUzgMWnRt2ryMnj4tN9Oz4O3Yidoqkxz726iJ7X1FnRgNaG4OGLUItLfYDKTBbuSKzdHyGA5zsBEKVmz0FKL9HdD66D44alUddg1MUAbphxBG4ghh0mZg8DjsXCCsxO547xvgScK-tGt3_I8wEyS-D_-bEElaLPnW87wFoLosHIZucf38PdadWxk6gSt3MRdErLHeP42DwsVwv7vF2b1aTek5au-f-FUXTkidyEfKKuHtmIS3ZKltyJ1Pw", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci0wIiwiZW1haWwiOiJ0ZXN0QGFwdG9zbGFicy5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiaWF0Ijo5ODc2NTQzMjA5LCJleHAiOjk4NzY1NDMyMTAsIm5vbmNlIjoiMTk2NDM2OTg4NjEyNjU1Njc4MDQ5MDk5MTMxMzA1MDcyNDc4MTQ1MjY5MTM1NzAyMjgzMTY0MTczNzc5NjUxMDU2ODE3OTYxNzMwOTgifQ.C6QG9WyEIAqYEiLkY8-5yqTKYtCzmnu2RM4P7iqr17toRXhL2ZqCiQYgE2TpY60RlOqBI7_aiHOlxJRvF_iQghEQQSWkgWhkcjVkSvBJW0IHm0IrSRl9ZytQHi6x0vPa8bUff5L--9JfxMiH27wOTrGtTA1n8Fz3G8JKQfYNQF2VawzytJu3lywduRj6pZw9-FFTgPqPsZWQvwhiX75Tgud976CpDusKOrPAM3rA9fXgKo_aTKeOPiEIm11ezI1bsOJ3B4JhsxLT5vszZ11Ywytst8XXwqWHjnulkJWjM9QfVUJhsO-jEQ5T_dYDqMVnnkdzjJyMRbvgbyNPUkvx8Q", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci0xIiwiZW1haWwiOiJ0ZXN0QGFwdG9zbGFicy5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiaWF0Ijo5ODc2NTQzMjA5LCJleHAiOjk4NzY1NDMyMTAsIm5vbmNlIjoiMTk2NDM2OTg4NjEyNjU1Njc4MDQ5MDk5MTMxMzA1MDcyNDc4MTQ1MjY5MTM1NzAyMjgzMTY0MTczNzc5NjUxMDU2ODE3OTYxNzMwOTgifQ.bMYN2xPX86KhgBzGbC4qsV-daLww73mJ3NpNvzxJG12Wk3PjnCe6e6sN8_QF4ou3v0xOR8llSQFZ3G1Bn_ZpZAEqLVQs4h-R21LUuCiUB9fRA8i-YzbeahsNiZYTdrgHOM4iLSPn1y51xyhPS66uHMjuj4iqNvao5Uthnn6s4fbcX6aOlg3Z9jeq37Y13XbXa75pK7lquNtnd9lF9BYb8jZsw1MNhIHqMU6rGIAkdNJDCI8CJF7SzVUQgaU_JLyHNcBGaPBypg179KMQXq8Uc-JfTYnz44iR5YZ1tycPB5gDBWydHWjpVoY-0cSxm1PiI-Eb08Xskawuax2967gAzw", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci0yIiwiZW1haWwiOiJ0ZXN0QGFwdG9zbGFicy5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiaWF0Ijo5ODc2NTQzMjA5LCJleHAiOjk4NzY1NDMyMTAsIm5vbmNlIjoiMTk2NDM2OTg4NjEyNjU1Njc4MDQ5MDk5MTMxMzA1MDcyNDc4MTQ1MjY5MTM1NzAyMjgzMTY0MTczNzc5NjUxMDU2ODE3OTYxNzMwOTgifQ.yVOH3HxPvCebPm4-OBeih6YdBgML2D8eMcWmwYFqG6jJqJZATEukkH0CMQPlsuKxi0_qJ1UUBy89ouFS-aaTwgfhjDx_pqYgXfB1etR4QJBmu-9TuDgvc9KLD9TGWbi1qwog_wuccUWVyqHcS2BkfKWTkziXzFmZH3ayqUJaEGtYAWRyiKiklY79adOHzi4VgN1sUHhpIHxOkBF80iKP3eEHpNgy-JsmeMlgJUY-70yHT5AUrDrFDKYBlU5MLB-3zngre_IPRGqV7tG4KjGelSJxcunr83CfNIllfDV1q6FPiLrEh7tsVYnqFMmrY9jGHKNu5vEnG4JkcBtCoW5l_A", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci0zIiwiZW1haWwiOiJ0ZXN0QGFwdG9zbGFicy5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiaWF0Ijo5ODc2NTQzMjA5LCJleHAiOjk4NzY1NDMyMTAsIm5vbmNlIjoiMTk2NDM2OTg4NjEyNjU1Njc4MDQ5MDk5MTMxMzA1MDcyNDc4MTQ1MjY5MTM1NzAyMjgzMTY0MTczNzc5NjUxMDU2ODE3OTYxNzMwOTgifQ.H8U6A7rgUjWCniDx8VyGOPgFTBYsvlKbYbT1FeVYk1PlRgITjl4jy4W153ysu88FMembPSNEMfTeWQM5JIw8kRvBUaVdjfDvcKsen_dG95kAzstmdHQs7PCmYVzfILZknWNArqkKoqx2EPaNaO_URcPxOQy83vXkFgs7Do0k6ORgOtzZsYy1TEvuXmxyxRE7qly0aUB56xZq0Wv_FSa-pg9EETaBeNoZoIzRPIpymhU4oHhy3hthXzUzUBAKFlpEOu7ydjlA_eyhCT2YlDXgjFx_2kLo0HUIzY3-sNvkJljXdJhmQI9Qqm7eROQQKG6id-1pXIHKZFiaMh9LwzntQg", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci00IiwiZW1haWwiOiJ0ZXN0QGFwdG9zbGFicy5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiaWF0Ijo5ODc2NTQzMjA5LCJleHAiOjk4NzY1NDMyMTAsIm5vbmNlIjoiMTk2NDM2OTg4NjEyNjU1Njc4MDQ5MDk5MTMxMzA1MDcyNDc4MTQ1MjY5MTM1NzAyMjgzMTY0MTczNzc5NjUxMDU2ODE3OTYxNzMwOTgifQ.KDdu8SebfBNRv1_We66cxm6y9uRi9IBUn66wQD133m_lSpEGP9GUpi7Soe9CSENfZB69PHV9F5dTxXKj75wwGfzIRfcp18hyORcZLmmyjZ4icSDlnh1h9uNAd5ADqmQUHeo7vFlOIP8gA8fGG29pkvupJhtCzABflrOYKljzZYZ0fZRE_5tvyGXAUT6VrSN-CkVxrppfI0ZgcuV5q19LofyHg0tl7qJv7e3VNPtREfk0XJws5-fGqBImN_zjTxWQoDJBS1q57Fs4sDe5ZstWAoWzSvIJYfLQpdY5OD0uqqOqGMzl17Q1tCj0ajorSeUeKoRjXZJm9CwFriQZWOPPJQ", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci01IiwiZW1haWwiOiJ0ZXN0QGFwdG9zbGFicy5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiaWF0Ijo5ODc2NTQzMjA5LCJleHAiOjk4NzY1NDMyMTAsIm5vbmNlIjoiMTk2NDM2OTg4NjEyNjU1Njc4MDQ5MDk5MTMxMzA1MDcyNDc4MTQ1MjY5MTM1NzAyMjgzMTY0MTczNzc5NjUxMDU2ODE3OTYxNzMwOTgifQ.km38lnzSyfyra62C8S58gE3DbbUzfpSX3uvb3NxKWq1LbrgvkB1kcOq7YQFTCUFrb6lGC5qMPJSJlGkiycdz5iL-SM4MiMv7Jp9YEJw7IEG0ExdZ6FJNblYUNuBjF-up3B6vJ31wy8h1jJa1QsMB6JFqfJtshLURXJ00fM1WkdA9smIpEv6nrfv83yUZr8DNYQ1dY0HZlipPaGeGCCmSXJxFYQxFLVxp5cqxS_qtyB7y_utu2E3RiPwn6Eq38n9-J2CmYPSEFc4f4Un12Kc-_VzMMULTMP5jfJZt0lGariwx7ZdIsXh9956ZZ57NULs1f0LTWk8WozPqyfUFFpISTw", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci02IiwiZW1haWwiOiJ0ZXN0QGFwdG9zbGFicy5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiaWF0Ijo5ODc2NTQzMjA5LCJleHAiOjk4NzY1NDMyMTAsIm5vbmNlIjoiMTk2NDM2OTg4NjEyNjU1Njc4MDQ5MDk5MTMxMzA1MDcyNDc4MTQ1MjY5MTM1NzAyMjgzMTY0MTczNzc5NjUxMDU2ODE3OTYxNzMwOTgifQ.HwOk4Jm4n_nuW7zQJqbLa5apIf9OH1xH1VkJp-is2-7GpiSTRRjsbp38VVLRRFL10YWTcrz9clf3ZMjz5_Pm4B7euabeFkTq1sLt6LE8rBZg-ccHvWHHkOsM_9fEYTHne5iGL8fSuF9vnK1SKbCw0i1SBGExrm24u2HL6yz8OhauF-rS0zJ0s9Re4snmM0SYjBJO4XOzMJ-B8vwJSQNbKz5nNBoBVHifJWsFcVmOvn1NXYxrYSKtDgu0KTMmpesc9NBESxwg9hx9npoVd9-ncbH_cJZfBvR-dsADgy8HFt27bnPWk0Ps2LZVxmKPruJLqmY0VD6Vz6vU3AHgsgsQqA", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci03IiwiZW1haWwiOiJ0ZXN0QGFwdG9zbGFicy5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiaWF0Ijo5ODc2NTQzMjA5LCJleHAiOjk4NzY1NDMyMTAsIm5vbmNlIjoiMTk2NDM2OTg4NjEyNjU1Njc4MDQ5MDk5MTMxMzA1MDcyNDc4MTQ1MjY5MTM1NzAyMjgzMTY0MTczNzc5NjUxMDU2ODE3OTYxNzMwOTgifQ.A8PPakHK1SiaEJ1cp8G-_t7UkTvDYX1h5TvBT4Cbp3WVUh_JHO_CNPD8_M8SyIMKlEAObKyglio-MXzEMkxfGnwmWgt2BtIPqia8BATTzbhYfiSM88pbFKGVBcddaJv6aUUBNr9gYim5r11tLBiD_b42xw6mbFzIwbbJ5mkbeany-N_0BrgBi1zmwRo8AkcdABlVEd19qe66vd-37t3h7wQZbILQ8Db-Th4Y41KbsBGF55TuBE6E0xeqRVrfyYsJPSZUi81OChPT8C-pQY2HWRBaaPt4LFgbqn9VWpagCjE98GZQE8F7Y2CxBwzjEqPZgNLJsFnoXiMmLLL0i8Acww", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci04IiwiZW1haWwiOiJ0ZXN0QGFwdG9zbGFicy5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiaWF0Ijo5ODc2NTQzMjA5LCJleHAiOjk4NzY1NDMyMTAsIm5vbmNlIjoiMTk2NDM2OTg4NjEyNjU1Njc4MDQ5MDk5MTMxMzA1MDcyNDc4MTQ1MjY5MTM1NzAyMjgzMTY0MTczNzc5NjUxMDU2ODE3OTYxNzMwOTgifQ.DCEHEMvxm6n3u6RYrv1hOGe9HPoAPcnrhRHEPsINEX2729wk07Bw8QsOfT5dRr4u5CG5DpgZrEN1NAoGO5b_rTmMxhVNoPUgSb3PkqaalGgDjJ5oP5wu-PWDTojevI44MHNtYslOj6KIIrHTZZZYqO_ev8S9uPZ-U4FyPgB9ZjAbMjgNIz5RqZyoYHHyqCEvWA8cIE20as-mpZ24ywQ6nB_BO8KvGfh0kGTV2CBgXlfnNAp8egdiN-x7IGihOTl--XbTK_MZWsTVi56z46RhTvuwqx3TozGUu6Cvoyqlnq2bYx3Az-tCU87Wm2qSeHJ28HyMSc4MF1rJ9PLyJ8w4_w", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci05IiwiZW1haWwiOiJ0ZXN0QGFwdG9zbGFicy5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiaWF0Ijo5ODc2NTQzMjA5LCJleHAiOjk4NzY1NDMyMTAsIm5vbmNlIjoiMTk2NDM2OTg4NjEyNjU1Njc4MDQ5MDk5MTMxMzA1MDcyNDc4MTQ1MjY5MTM1NzAyMjgzMTY0MTczNzc5NjUxMDU2ODE3OTYxNzMwOTgifQ.xyW7ZEq3ZIlVWnpaZEPYOfbm6RomIkVHzCvBlSb2TmgMp4wl-2je7-Alpf9QzvPkT88764rqJckx_q_8fD0yvechM8eKcP1dpvGIpzuY0LglNssmem-K5S-s5h4hZJxCxGfQEQjD3mHeHp9yDXVIBATGUXG2ZAXWHrZdESHl9Zxj9t-7hhqSYw5eYjB6lWsyRijE74DMPyXlNR2LVtaTqVfisiluPnnfoDRAUFBxAzM9H2VmoFayJyiiGMvClDg-EicAuneq6xjGsrb1aOCCcBK7OE9JgyAVQ6rq5flSPrh-V1AEDiDfvhKiHIpfxyJdnGU8clZ3_MbXPj0W6xtxzg", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci0xMCIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6OTg3NjU0MzIwOSwiZXhwIjo5ODc2NTQzMjEwLCJub25jZSI6IjE5NjQzNjk4ODYxMjY1NTY3ODA0OTA5OTEzMTMwNTA3MjQ3ODE0NTI2OTEzNTcwMjI4MzE2NDE3Mzc3OTY1MTA1NjgxNzk2MTczMDk4In0.U2nRCAghYwUeP2bY-STkolILxPXvtg-sV44RxwR4uvvFJDIGn1ZWsdpemFZaXEr4szsAmEBoX-PLPdjKhnIPbIy2nT1sNWq33fp2i6ioruP9i_ndAO4qVwWPEtlonMSWfTXbIEVNB9f4WHhqxXpM7rtKRvAjDW4SezjQohOsspBz-rCP8-2gxpSlPf5A0eCFVAasgBg0uRdLPYQnws7r-bXuh2Huv1tX8MDjmYjshFSiJQrjRLZ4sfEgOrcrHHUfJptf16T9C5-R-pm-oWOIpXGSUlBz8QJAe9Y5DBgTOiej92L9bDkKUXTwt58iwPXAjBKBeg5394jSUacrgboHyA", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci0xMSIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6OTg3NjU0MzIwOSwiZXhwIjo5ODc2NTQzMjEwLCJub25jZSI6IjE5NjQzNjk4ODYxMjY1NTY3ODA0OTA5OTEzMTMwNTA3MjQ3ODE0NTI2OTEzNTcwMjI4MzE2NDE3Mzc3OTY1MTA1NjgxNzk2MTczMDk4In0.eChHtb21NqZyv1FMRMVinI7lhqXMcTRtYFnKUZa2G5ahhm2ZLdAlRRwzwHm3iONC3Nxm25Qyd-kfdRio0KRlDAegSx1FMeW_F2LQpWk42mzCGMqad8VvP8p0We0GAO7sOCy36KvTcSXx2dWTDHWK4p6nXrF0uI8xkU5Fr76TE1ThJK4K8MGy9OY-v7FERaL6b2-0Ui7M8FBHufQpiJ36h5aPETnC6bwII4yCmrUfU0B8tFPq_yp2nDhze0kAa8F1lQVLUcBteZ07MNQ9u2XvelwxQ94MI61NgRGFmBZfQXPRQIpcoJHc9H8hEMzVWMCYNIZwfiTJKxcXnlKny2fx6g", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci0xMiIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6OTg3NjU0MzIwOSwiZXhwIjo5ODc2NTQzMjEwLCJub25jZSI6IjE5NjQzNjk4ODYxMjY1NTY3ODA0OTA5OTEzMTMwNTA3MjQ3ODE0NTI2OTEzNTcwMjI4MzE2NDE3Mzc3OTY1MTA1NjgxNzk2MTczMDk4In0.BI4gvREMhdH7BleKF_rhutgBGsi4iG2nXtROKD-h23BLfcI7Lohq9CtAQC7qPi9HJszQxfIOyp79yuVKl9xT5pDO59rFvVPgcH4CTya4CkuebzC3avNv4kFrX9KlF-Ks5z1oBghhutxoXfSntx5SIQvGWeiXQ0EYYqE_uyrx3o89tMjTaDqpc0_vOIpmfU4bEG0yZnsnhObAOjOxr2id2vHlS2ECzCMbUeaHi_o_dQblIpq-eBVp0xjQo1j_2480MzPa4TtsnsvugHZdA3cCzThyLFnj60hOV90EgBgHpnjpWsmNBlocR3A3ZNGNzp5j0ebA7axiMxfIY89reEbbcQ", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci0xMyIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6OTg3NjU0MzIwOSwiZXhwIjo5ODc2NTQzMjEwLCJub25jZSI6IjE5NjQzNjk4ODYxMjY1NTY3ODA0OTA5OTEzMTMwNTA3MjQ3ODE0NTI2OTEzNTcwMjI4MzE2NDE3Mzc3OTY1MTA1NjgxNzk2MTczMDk4In0.ttKtdAnnu615SXnZDF2sZunRFKIO60uuYRnGaAdgwWlX4oQpg6pSQuNN6l-2ix90_BIzR-9P1UWulcNFG8MyKO2t3QafFk-sDciET6MGRejYmgJ3XBO281iG_jNYmrcRiHOQdB9oUKQdBQkIj2uLYFmC6J_zxH6R_Wce_wAwRmi1Fa3-LM3BpO0zNNd_GT_c8XC7qHDMjgBjSt7X25Y6o71VayrgZDhefhlyRW-Q6vFyk4a8g2tPUCgucFrSdATemiQz5peEWCkYaGWR1SMC89dSj9ugeBZunOwfoRzheE-o4nL_TPbQVUdpgJgZTBPWhw3hZnagS1_-a5Nmwv98cA", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci0xNCIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6OTg3NjU0MzIwOSwiZXhwIjo5ODc2NTQzMjEwLCJub25jZSI6IjE5NjQzNjk4ODYxMjY1NTY3ODA0OTA5OTEzMTMwNTA3MjQ3ODE0NTI2OTEzNTcwMjI4MzE2NDE3Mzc3OTY1MTA1NjgxNzk2MTczMDk4In0.Z1SFWWjSJOXdiE3pBVmjokbOpj842YpgQmrWszfptGTwHADRL8zxSqE2R5gexCI_NlGizbEu33VqVGoONC35ha51wF2IGOCS4ziiZxMFzB4ZIjkCs4VmFV2ZUNyVkoVj_KWg8BqtMj8qVry-UlE_PHKbmhSWkRCSA64XwNb_wVzv5Ae-CVb2-B6zwC7HnpqAmHE2Eles9sDVRRqsagoi1NIoA8S3e1lTE49HkqhQz9bRC6AzLRJJJinu62_I1I4IM1Ub0rKSGlHompTVsKTRjxAHUqLjXDYAQaodZXuk-HDpQW7cb8rmRzOurYwMerFis_TMglTbJ0ThAuwnENGhyg", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci0xNSIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6OTg3NjU0MzIwOSwiZXhwIjo5ODc2NTQzMjEwLCJub25jZSI6IjE5NjQzNjk4ODYxMjY1NTY3ODA0OTA5OTEzMTMwNTA3MjQ3ODE0NTI2OTEzNTcwMjI4MzE2NDE3Mzc3OTY1MTA1NjgxNzk2MTczMDk4In0.cv726csl62bGHNLalP6a6JuwL1arfeZ1gaUfvGcLl6Rj-NN5a7e8aPTAQy-xMFQwrObCcHLuA6d8kMYUeYsH2HaIrtAzkrK9iQxaYsJqt1jIJ2E4pm0eByQ_rt4C8l561V4obrwRIfxmEVNJe2AT6wGPZL-mOBo3VNTpr6HnBDBFcFBMB0sXGW4tU14wfMfxREfyHxuOcR3CmGORDwgCIrI0rQ97ZktL2yTDQX9n93O8-unWqiABwT_h9NA2KPJinZ7m45o9XrA666-pSQBuW1qF6Vny-MvRt1xdmQtWYf4qreLxC3xfqCyH6PxJMV2jo-RRDoHDmIRLTdjK5-PCcQ", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci0xNiIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6OTg3NjU0MzIwOSwiZXhwIjo5ODc2NTQzMjEwLCJub25jZSI6IjE5NjQzNjk4ODYxMjY1NTY3ODA0OTA5OTEzMTMwNTA3MjQ3ODE0NTI2OTEzNTcwMjI4MzE2NDE3Mzc3OTY1MTA1NjgxNzk2MTczMDk4In0.Da3b2p8ZD8tsg7Fal4XW6c8keRNdBVyHaWvcRzu5e09TRYKhZOhLlLa9QlHeJooE9fPZUOnRpqj8GHkWGKS4M5xdzVrB56FrMTikFU6nDIsSML7OBtx0DRJtQaScILfFcprdKUJLpyGTSG9xbMt4jhbOdJIc1ENug4e_RsyxSm8t7DJVawqWjNWLbAQyoY8APhMeoy2T_M-iDN_BdzBmDvFFuq_7hGFYMDaEJXNdFlVDAf-mPVQ_1Rum-WswJhOCrfyytiHVioZIKCFBE1tsslBTmY3ZQw7gNGXtHRrdZpXUPQAaOPPmBh5Fd2qLz0xq_jl6FBfz3hJpENW8oVICRw", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci0xNyIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6OTg3NjU0MzIwOSwiZXhwIjo5ODc2NTQzMjEwLCJub25jZSI6IjE5NjQzNjk4ODYxMjY1NTY3ODA0OTA5OTEzMTMwNTA3MjQ3ODE0NTI2OTEzNTcwMjI4MzE2NDE3Mzc3OTY1MTA1NjgxNzk2MTczMDk4In0.W4NHUzOIpwW5L_aesqISGVleKLEooerDh_AoJupZKaDAXNLe2LM43WC0eG_DAVFCRul1FEPGmRIKP2S-oKpbN7GsSvfoGAcF5z5HKOtHkq9cfea4ApCPJBCCqAEJ6FAkpkN-jnxsBCKn6N-YxO2pu1megKhrTIgeFfLjYBG6B6vsd30A4C-Wga-fECFNA-cnoU8EotEWbtcJ09QsTR_6y8kBTqEmdiAMzh-5GjrEqjhD8GRkx_pVpTj_Zmfue3vkoVQlAeHwRuctrZGDXI4s4N9XSGEVAmetk72jTNS7Bg9DTsJW8Rx0eUXNaFnCZPqAAAq8j0CKcJ3LD7qmNtefCA", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci0xOCIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6OTg3NjU0MzIwOSwiZXhwIjo5ODc2NTQzMjEwLCJub25jZSI6IjE5NjQzNjk4ODYxMjY1NTY3ODA0OTA5OTEzMTMwNTA3MjQ3ODE0NTI2OTEzNTcwMjI4MzE2NDE3Mzc3OTY1MTA1NjgxNzk2MTczMDk4In0.tOO0QELwEyZqj9XGbqwg8N3ONrp29XvRmfByvNOELIZDZZrv4olvLinkAld3XBtwMAzHnUOnqYZBZ6RU_Y3alCwTmSXo9DPEH1nFbWN1ZqLwi2QvkwrW2aaNd-haGvhgN-IoL2JM93yzqlehfy6wv52smsGk3_7Q0hQLqv0KsqpF3MbIs7MVDmHSuV0fo6DRf0zL3OGjrRJqUz1BeRLbppK-RYeEhp5pPPTh4xdDjO70Bthk3k6ja4g5Ow0ozL9hbS-6o0z5vwJftg_ZEJ-KH4A6pEPpyffKj96OMJNpyhZCJjBGWI6XzvQobav3zrNh1ZX_zFo0VlZYfYmIubG5Jw", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci0xOSIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6OTg3NjU0MzIwOSwiZXhwIjo5ODc2NTQzMjEwLCJub25jZSI6IjE5NjQzNjk4ODYxMjY1NTY3ODA0OTA5OTEzMTMwNTA3MjQ3ODE0NTI2OTEzNTcwMjI4MzE2NDE3Mzc3OTY1MTA1NjgxNzk2MTczMDk4In0.sd4WpQQjZaojofmkcOY1V1tZ-lslRLMZCKpUxdD_VR_pwDDG5p5IvkP4HVQQGAuFHcf0N6laJZCTA-KeLsqoKP7wqAl3NeG3BpQeWIiZjaw_PIWpIe8ad6nZrRUyT-GCPAHHd9y1nKPIQAjDPG2hFqt3CU53DNjX2kG1eyOgLnxr4LH5Ipz9XdQMK-NBubse3qjH_RF8-2vzA_QCDgwiLqKsUSsQbwht4P_kUxbQobSSwq44wQLV2HSP4t7Rm0EWuF_HvFjO3XzJK6ANDsKQeVM8rxGY0zvAPuRwzDxZ2dJB2FkYyT-NmmlXehJag6LcqiKBPyrXqv8x3Vq-EGI6CA", ]; export const TEST_FEDERATED_JWT_TOKENS = [ - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItMCIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6MTcyNTQ3NTExMiwiZXhwIjoyNzAwMDAwMDAwLCJub25jZSI6IjcwOTUyNDIzMzM5NjQ0NTcyNjc5MzQ3MjM3NjgwODAzMDMzMjQ0NjI4MjExOTE3NTY0MDk0NTAwOTk1MTk3ODEwNTE5MTAxODcxMTgifQ.fZPN9kj5H1xf7YS81Rll_3-BC1yOIngoAmr4rFdvMtLqRxNPfLncyUFjsTfsf5USh-LwjQli8fb6uDSmnueGCbQQyw5CDSaALFmSMqzzr_ZezQv8Bv7iXrLPKei9Xp0eogoYsbb3_2PEu8DxwjXAD285uj5QPx0cTaoo--yf80rvvQYbHJp62XEd82mpM0vvaZqF6T_33STfj06Yj8B0RhAfKTSCTCa_7njriykbxIN7O5b_xPnhkRSJIjqD0ZmvNex4MuxMaHgd6Zgs9OIymzYh5dgsrC4Z0OawXCjK56N7SdaXwE6iFRF1g6Yy0pFxhMsX6_KtZR3-xzDndUvxwg", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItMSIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6MTcyNTQ3NTExMiwiZXhwIjoyNzAwMDAwMDAwLCJub25jZSI6IjcwOTUyNDIzMzM5NjQ0NTcyNjc5MzQ3MjM3NjgwODAzMDMzMjQ0NjI4MjExOTE3NTY0MDk0NTAwOTk1MTk3ODEwNTE5MTAxODcxMTgifQ.N7s0TZyE6bRjxWPGIlpjVb9c0jI_5dWgJsdWyYj6WQ1FEK4zb4b6nmCjHAJ-3dVrU9vJkOZruWqnpk-c7KcbS4Ouq4TzQj6FMbE4DBDvG0GF_TDvw5-Wbs_KU7dWcStqvDaq1ugzs2ZVnYlIp_p-VfK1kTY-N-4-nk2Xmv62mStF5ShORBUOraKmrWuwC6gnYC6-srZbvufdN-9GOXqMNiJMHonrEM66qDjsSCl44_lmj91ze5GzLKv0ggCNc-ZVm5Tj4fmre6Ba6RUxNi9xUHrzNoEZHg-Y1ZlNXgfozw3pkSrA5CDp5xonjVFfHQR_J_sXHKozk_9K3dNkOeBA5Q", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItMiIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6MTcyNTQ3NTExMiwiZXhwIjoyNzAwMDAwMDAwLCJub25jZSI6IjcwOTUyNDIzMzM5NjQ0NTcyNjc5MzQ3MjM3NjgwODAzMDMzMjQ0NjI4MjExOTE3NTY0MDk0NTAwOTk1MTk3ODEwNTE5MTAxODcxMTgifQ.fLiHkTWpSR-ux61nlRLBIGE8XDYP23DE1h9VJpb3CXX-LYj3A9B7YvvLRXUZ4Ffl3DLV97GsT_tHEEB71VHiJ56xpwxUWxkHdgWgxFLaWgtuW4kBvydIvyMOWbYIoeO2Np6Ef1q58VjY5xs8RAMSFHhY6VDJ0vTZn1hgw01Qf041boIFNjIYvxSvLtA0-B99uq0mI2TOquLBjG-N57mnukW6oLSWUNOC1ysmrWavYIklTJxTShOpufNzB-oH3zD7O_INSWnboyIabGz8TC2njMd4mub4KwlyZJZ00zyHs5sMLG1W6M0V8RHrPIas1G4ic0drvHRlkiLLDlCcEZkYbg", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItMyIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6MTcyNTQ3NTExMiwiZXhwIjoyNzAwMDAwMDAwLCJub25jZSI6IjcwOTUyNDIzMzM5NjQ0NTcyNjc5MzQ3MjM3NjgwODAzMDMzMjQ0NjI4MjExOTE3NTY0MDk0NTAwOTk1MTk3ODEwNTE5MTAxODcxMTgifQ.Ccm2d37bJ1GGaodtzztPWlmp_Aa8XdrvtIpB84JPjJKlijIwvRiENC9p_9EwinpTEAZqyJHDniHw1mn29p1tXjoA1rGwj0YmcbtS3oYdXgiva8leuPzAUfRmwIxateIjIoY6ggYVctPLa_yIomVPhB8TBS2sGq0kTA_VAiQ2MnU8RuPJyXhl_bE27DbVLzTaESDIN56SO7Hwz5EwsSNzt8hiFKScppRpzUEEQ2EIIUkGePpnVxNtGAmi7DXVvd17AoYADnjQZCelpQcBE6_WUMc1_9MHUFVTJwTdf3lPYIlGAXCqmHNvaz1sUf7gzrkZCub2BYzhq8zg458EvG8E6g", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItNCIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6MTcyNTQ3NTExMiwiZXhwIjoyNzAwMDAwMDAwLCJub25jZSI6IjcwOTUyNDIzMzM5NjQ0NTcyNjc5MzQ3MjM3NjgwODAzMDMzMjQ0NjI4MjExOTE3NTY0MDk0NTAwOTk1MTk3ODEwNTE5MTAxODcxMTgifQ.aMFGHKNeIHkBE8woc-jiTFAB1sm7RE0sCxQcNKkiaak7zCXbUrdKtImhht9yx_VmJ8e2FubH8eVh92P8tlIGaTpwdtu5qq8i71l7nX3Qk2DFxUAbAkG92suTnzCQE91D5Rtt8dlvmwHytx-a7Dr0Gv4M1JPon1y5vSkBrSsLIqiK6CA9othikadZRVUwO0ubckNldlhPjE7wz59Qf9Q3UNFFcIFVaGM5BsLIpMiZZOwEuNqitD243kPXR3gBBmPwYygMV_HtpSA8IXl95Aojg4KftZFJG7cZkLd-g_tz5KW-4YptrB7-3URK4K4IwNQJ9XUHbzDrMcYaY534YCVoVw", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItNSIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6MTcyNTQ3NTExMiwiZXhwIjoyNzAwMDAwMDAwLCJub25jZSI6IjcwOTUyNDIzMzM5NjQ0NTcyNjc5MzQ3MjM3NjgwODAzMDMzMjQ0NjI4MjExOTE3NTY0MDk0NTAwOTk1MTk3ODEwNTE5MTAxODcxMTgifQ.HZFhdvodQLF3fGH9u6beqWsfugFS1OHkZMMhkTWRVhbzREs5g91_GzJcchXetotbhBmcCuQ_apLFFwOWHyx0VFTm2WvJdd1uUYrn4sKllFok9709ZLOfBlbo4218C-xA8LEIBoz6AxXfm8CVIy3FFjUGaKkniWjCdofWa6bSkxCXqMrGk84IaQP96S_d52ooG_B3H-Gb9mbEYRgBP3zEgVEq0bqMiJQJ-CNPBIeKAkUp189kOS3EHhheggNPbR8g3ee0AtNXlHbDDWdIQFb223ufFuX6igA5aWoIUFIBZ-URx0oy099ua8Pem5GuB-rzaC6BN14AabsqCievoGh8Yw", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItNiIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6MTcyNTQ3NTExMiwiZXhwIjoyNzAwMDAwMDAwLCJub25jZSI6IjcwOTUyNDIzMzM5NjQ0NTcyNjc5MzQ3MjM3NjgwODAzMDMzMjQ0NjI4MjExOTE3NTY0MDk0NTAwOTk1MTk3ODEwNTE5MTAxODcxMTgifQ.WoFAo8QOdYU5TWFxFo01n1ZfJaMlhbMb5cq82x0YvlBnA39ureqQ4f5kiB5Y0fMzqhJsfzVUq3lZBmCK5xYkhUUM-IoYhxW0R1efe7Hb1I1rD4OLwntxECSEvuftTqOYPDQRzatI1JORMrWYmRYsPlkgyrlnpq7GkVVd_gjlrTPKwMNTBxc6oXjgkjl7MqAir0KIo0gii-Yb_ApXHP17QpMjL5mVgqjYLDY3p5FeKRV3N6UyMCcIyWKDRs1qkeskhku-b52t-CU1jiaYtfzRI_bG_IMJjInT4QpFmaRr3sYS2sz1fX8oXSWxAxgbgc4nYqlAHJ5r6v-UYdBVGCA7yA", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItNyIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6MTcyNTQ3NTExMiwiZXhwIjoyNzAwMDAwMDAwLCJub25jZSI6IjcwOTUyNDIzMzM5NjQ0NTcyNjc5MzQ3MjM3NjgwODAzMDMzMjQ0NjI4MjExOTE3NTY0MDk0NTAwOTk1MTk3ODEwNTE5MTAxODcxMTgifQ.Nz9PusTXc77ql77jZwMaA5qM69k38kRa7R9fKMIjpQ_ZFCyGa-d43cy6z0iqkjox9MAooNc1iE14aYAa-kFYGl8HREbmRD8o7pM4QaUi7J29jJcQ5xSTQQPH2skgQ3Yp32KsAFP1KvLtl2k9IGB5D-4uinpjxcfjFP55Xv50IkHLS4l3HoxBKpg7UzcFTfZ8hVsHwH7Z34LEb5HG7ZP-68gCTQjlDocZu5fXKOOZSVyQYQQ7cHni_y6c7YmWueDCCmZAbR1eqL9ttVGEmj5hzXDqsKPZuAlLf-nZgsIv3o3970D6mcgqdDy5qaRRm2Ch6Y9E2Z7pdNRImN-nY1mH6Q", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItOCIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6MTcyNTQ3NTExMiwiZXhwIjoyNzAwMDAwMDAwLCJub25jZSI6IjcwOTUyNDIzMzM5NjQ0NTcyNjc5MzQ3MjM3NjgwODAzMDMzMjQ0NjI4MjExOTE3NTY0MDk0NTAwOTk1MTk3ODEwNTE5MTAxODcxMTgifQ.f1XRod-ZDlUcbkxAfgKZzSUTs9TuObPw0_K4EE9SsNUf9cDz976E3StiqNqtbuT5kWt_eb8sUsy82hlr0aZD5vMwlyM6J_SSp_lqsxZAKgmLdB07-YO0acdx0ElRNrFjVH8JlDKrPPhke83f4FU4lWN6EEnx6JqcNkh2YEA9r1FektH-54nc1ucjfBZwIgwC3PAex0mfYLq8E9g-cWNPlAZhVCcqdK0q0WfD4PBDrmUBREPYoAsZI6vmBx08m3OuhUJYTCTd4EFijlZcY8vdIxzXwe7VsZm3GeavzlsOpPjMoyPk06VvQtqvTlEm_yvTcjVrVXmWwkFr_v1-Mu_dZg", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItOSIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6MTcyNTQ3NTExMiwiZXhwIjoyNzAwMDAwMDAwLCJub25jZSI6IjcwOTUyNDIzMzM5NjQ0NTcyNjc5MzQ3MjM3NjgwODAzMDMzMjQ0NjI4MjExOTE3NTY0MDk0NTAwOTk1MTk3ODEwNTE5MTAxODcxMTgifQ.nNETD85nln2HOqbJ1rQZ9keQM9TAwRJ0qqnUY_srBubPScowk9MxibHtUM8paDTKviGJY8G4GxCIb4A-Pk6CdgmbfRAyx8DMVf0Z-I_bfrVp64ZDU090fuZv7-uU0QgZYSvOMOibBz1oun-Ybuv5hqmruVq4OHmWcoB8fjofaV1GOauk7L4tAJ7nhCrBuZuPbBLCTMwYz7-0cLjPQ0L6bk9WcIW355Xu5w8hTuq-5ccI2zMyaFUmGA81-V5sVl_HTaX3x8X5JBi6JRL55De-BqQ8-TzJW44i2WU-gC9p6SeHnPXdQESjf8YdRmSumnupk5aoMOtYr2OVdzFM0O06SQ", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItMTAiLCJlbWFpbCI6InRlc3RAYXB0b3NsYWJzLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJpYXQiOjE3MjU0NzUxMTIsImV4cCI6MjcwMDAwMDAwMCwibm9uY2UiOiI3MDk1MjQyMzMzOTY0NDU3MjY3OTM0NzIzNzY4MDgwMzAzMzI0NDYyODIxMTkxNzU2NDA5NDUwMDk5NTE5NzgxMDUxOTEwMTg3MTE4In0.i_awHcWeU39k9no2klEajvTevA95naoquvzKu2DrS9lS_7Fm52pezCSb2e3M1ovvkoITpTb5IfRCo2PrP8AuGUv2srZU3GqDoyZaMYguvKJLLeqV670i4knGFWqfUegAJh1VB_-yN4nlbV9SXG7D7yk0WwWEUUGfWB7_NGqsHX2B84f_U_Dus14x7za7Y1t91EeXhzwCgZJMB0DfXT2Y3VUTU1O1abUKJ866V5pdQC7HJv2qUthmn-TlSIl6qac5dQQ14YxQtyEKXeTP74guxArcdvCsPuC8TAAnP_f_NxehFRRSQ-HJ3tJ5ym7PwQ4L1uaW5Rxc7duqsrk1JdX-zA", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItMTEiLCJlbWFpbCI6InRlc3RAYXB0b3NsYWJzLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJpYXQiOjE3MjU0NzUxMTIsImV4cCI6MjcwMDAwMDAwMCwibm9uY2UiOiI3MDk1MjQyMzMzOTY0NDU3MjY3OTM0NzIzNzY4MDgwMzAzMzI0NDYyODIxMTkxNzU2NDA5NDUwMDk5NTE5NzgxMDUxOTEwMTg3MTE4In0.Z_5NEdbvnP9kqsCrOPIqCrR8iYX9kCIFsCMFiU9ozmkNjCDHgU5XQKuYRfsi7Mfq1CQL7gZVtJsDXWmv6ENBRJFFu9BHORuTZrMZi-on5yVZVf4J1RaxcRAdFOCIznN6DT6DyAFxq0vyCutUI76BtmYr17g-SUrESUkgG4jgL0xIcMNcitKWQ35o8fYJWeaTAa2x3SbX1IgCAFdjsD6DLm-LY5t7MicHekrpkHDBv_PuP9xzxRbNJfGnNnnB41h9sfATqiIMJXLvUfuDKmN43MQAowODTtgDfnuLNwBuXkGOCLQmtLjdNYqLRGHccFwEsanfUimOCmsjRMvJSt1o7A", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItMTIiLCJlbWFpbCI6InRlc3RAYXB0b3NsYWJzLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJpYXQiOjE3MjU0NzUxMTIsImV4cCI6MjcwMDAwMDAwMCwibm9uY2UiOiI3MDk1MjQyMzMzOTY0NDU3MjY3OTM0NzIzNzY4MDgwMzAzMzI0NDYyODIxMTkxNzU2NDA5NDUwMDk5NTE5NzgxMDUxOTEwMTg3MTE4In0.Yq69UbPUVLTG6IMnqwiqf-sMnm42JMdTfOIv-8bjQfIPRQauofFeqEYY5ls6i41DbU9dLkMofoOshm04NI2zk0W3lE-6USak4Tq2xnnWYsPuWlXV7P1w7f6_KwPD8BYnGiWw5DTZVG4tjn3El9D8lPikkWlEAE0Z-aR1p3ezwzqIoRokeN4A7uxvcAzTWSqYQ-JkF_GAMbnLScfjXVEpCjiDnF-ydW3Aj6B87S8K_EWOKptFpswS1UVCuwVDm1wGouvK9WbBSAdtZhdl95p_geke_l53z3PZdjYMYrmtTSxJdBAL-iJ-UpODqzz8sh9rGXBv70wM14oW19IboX9q7g", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItMTMiLCJlbWFpbCI6InRlc3RAYXB0b3NsYWJzLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJpYXQiOjE3MjU0NzUxMTIsImV4cCI6MjcwMDAwMDAwMCwibm9uY2UiOiI3MDk1MjQyMzMzOTY0NDU3MjY3OTM0NzIzNzY4MDgwMzAzMzI0NDYyODIxMTkxNzU2NDA5NDUwMDk5NTE5NzgxMDUxOTEwMTg3MTE4In0.ZT_zGYMcj4hyzIAyqE3VAte_pxiPxF1cnUBpgcSl7NCIRCO3ErpmsXlvas438UO03tj8mqpyuwFuTEHjSAVZRSU_rOgGowtTnwBRBJJH3pFzvv3JE3mnRro_7nQWXRZqYzmUNAxzEEhn5fJQGyYXilT7Rc-5E9CHtcjxnpN-4eC9oNfQiw4hOG5nzx54PxQwirlLfS0l0zc4-qRmS31vNJBKIULD_6y0MUrr94dZk-M6fBGqGVuCLgMfh3jlCFgMjpE5BBBCvoodRu5mJ8aNWa6DgqHUlc3LXqL_Q9IezFS4KIP2KYASe10sRVRs16_dZXy_ng5Ny9shzNRKMZiNCw", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItMTQiLCJlbWFpbCI6InRlc3RAYXB0b3NsYWJzLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJpYXQiOjE3MjU0NzUxMTIsImV4cCI6MjcwMDAwMDAwMCwibm9uY2UiOiI3MDk1MjQyMzMzOTY0NDU3MjY3OTM0NzIzNzY4MDgwMzAzMzI0NDYyODIxMTkxNzU2NDA5NDUwMDk5NTE5NzgxMDUxOTEwMTg3MTE4In0.PDY8M4wnfh1gQ-DLnozLekWRCIJAL6y-8ceK7tlrFcLaoiNfnP2pPfgY-cUKAV7hEkKAt89PTUXOa_d0JUmjh0XkZUn28KqXK229Mnp-wUE114GD-Bu1rlQLQoJ5m_sWWLBEV4_FlKx0igyJSWb0YYYl5BfgxDGoyCnQTfXXC4Ha6OJQo88qcQD_K-PRmZ558fhAWrRJaeukegbXpGfw6Hhyw4z73GhYvEiupXuGB34UiWxWsTHyH9EzY61wIQQLGs0qjXMa2QMDEnApqWYnVWcug86IHz5JX5fxxmVz9qzMufc-WArplFnD5LLulZdg9zQdXODcyEyRZbtuBfEcdw", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItMTUiLCJlbWFpbCI6InRlc3RAYXB0b3NsYWJzLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJpYXQiOjE3MjU0NzUxMTIsImV4cCI6MjcwMDAwMDAwMCwibm9uY2UiOiI3MDk1MjQyMzMzOTY0NDU3MjY3OTM0NzIzNzY4MDgwMzAzMzI0NDYyODIxMTkxNzU2NDA5NDUwMDk5NTE5NzgxMDUxOTEwMTg3MTE4In0.cVzffagURHwPU-5c-NYAKoPF9_43d74ashqvCOzbWGL7PyQY_mNZs-2oev_QHXyrjl4PkmCvviiaawTKyQP9gWFFVfnyQYicP8M1gCvVUKenPYLpzYAp8SEUCISyKkDE3qPc73pf2FQZDl6815edBKiVaIoomdoJs_7QE28Ipo4d8D1g61cetE5sc_JMYDWg_PpeTdB5vBPuPKzr8Mc1zz9u8AJhLn8c-XaDDubhvwj36xsgVY3nw61FQxW9SBwLoTmoTakV57SP49Z2glzMrY5hsfrXyWynkJQadg-ZiJbpoqXfrXINdGr7y9Iboh2g18D7Cu3vlFpv_PQx6cYJZQ", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItMTYiLCJlbWFpbCI6InRlc3RAYXB0b3NsYWJzLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJpYXQiOjE3MjU0NzUxMTIsImV4cCI6MjcwMDAwMDAwMCwibm9uY2UiOiI3MDk1MjQyMzMzOTY0NDU3MjY3OTM0NzIzNzY4MDgwMzAzMzI0NDYyODIxMTkxNzU2NDA5NDUwMDk5NTE5NzgxMDUxOTEwMTg3MTE4In0.WEDo0H753toeCM9OnbeTL5ofJAAmjv7crP9FHrGA_YcPRnfMdmnjpa3cI4olloSDI2j69BGOK05CEjumCXjz-YPoZDgiEuJtDSEZA-1CRUXTMvbERjK47o2X82T_iVLRBVihDEbmyxAnCnwPNLTGMMr2-2o2RCzlHhOTryih-7CNj6ty9HMlOmlIA12FWj5Ik8G0BdDaWhBClaGh9UYiDKXWUvBLFVD_p8FA-GJ6D9ivwj10HIMHnYxCNxDMxBYytS0Kr64AJ6Pe5Chrhq2u-XlrnVDJVWmgoMlsoMAZ2EVzVOU_s_cHK_7QIaySaSTEO-rkdhFMulqYMHDc9JWkpA", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItMTciLCJlbWFpbCI6InRlc3RAYXB0b3NsYWJzLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJpYXQiOjE3MjU0NzUxMTIsImV4cCI6MjcwMDAwMDAwMCwibm9uY2UiOiI3MDk1MjQyMzMzOTY0NDU3MjY3OTM0NzIzNzY4MDgwMzAzMzI0NDYyODIxMTkxNzU2NDA5NDUwMDk5NTE5NzgxMDUxOTEwMTg3MTE4In0.WtLlWEKtNeI2HmYdIJam_bWLGxvOVTSj4ohxJuB1NBfSZxQbuAgQ3_pnXVd7uioQyUm5JEloG4FkJFYE7hmrlL5ocCqufws40HQJQx2bJm_8dePccMNRyjsk7Ya7_1dp0d5QEH-Ckob_MxIAawHqhMUGTExVXuk83STXCVN3e9HHzo7UiekuYIaAbSlBpX_ySkfAPDHvkKpXwg25w9zI3y0JrVGwoKlGNzwasFiY0RVtLNLQPpjz_LEdH9xappg36M75SP-q0lJO5KaWtmNHHTTQ11GXs3xXwMCn9mU6kk_sBy3N_GVtkSP_qjCAdHYKUPhx4Pe1Xajb_trvvCCk9g", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItMTgiLCJlbWFpbCI6InRlc3RAYXB0b3NsYWJzLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJpYXQiOjE3MjU0NzUxMTIsImV4cCI6MjcwMDAwMDAwMCwibm9uY2UiOiI3MDk1MjQyMzMzOTY0NDU3MjY3OTM0NzIzNzY4MDgwMzAzMzI0NDYyODIxMTkxNzU2NDA5NDUwMDk5NTE5NzgxMDUxOTEwMTg3MTE4In0.CFK5gunymQ7Jf7stOsWdEVO1y275eSefL0LsQku-Gdn_iWVFmzY_ASQqBJt8jmfM17zht5NUrASm095yn3vDRYnx-CgtDwJrpF3jeLbt101ld8VytJxng4CjyznzrVuSPLM4DMiUjILG4vd9wNOkEUgPQzu5qdqEGckxj-c1lMpWhyWDR9pZaX_BryNGNdQvw4auJFuHcWl4HeVLYhdcZulbz_OAq1huYZgrjzDgVrMjXOxo2SF6ObmnJzrRllrynwingLAsGQtiNWppVNcpeG-DxFhWYhnb_w-oTk2HcwFoecWr0R_ran_UY1n0aPZ_2MzZ_NsIaeG0VyIk0SxbHw", - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItMTkiLCJlbWFpbCI6InRlc3RAYXB0b3NsYWJzLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJpYXQiOjE3MjU0NzUxMTIsImV4cCI6MjcwMDAwMDAwMCwibm9uY2UiOiI3MDk1MjQyMzMzOTY0NDU3MjY3OTM0NzIzNzY4MDgwMzAzMzI0NDYyODIxMTkxNzU2NDA5NDUwMDk5NTE5NzgxMDUxOTEwMTg3MTE4In0.cOZY1MKhMYDv6GNAI61ojFKtZS6M1a_5eOkuVVVFk1aEpvMqe12irXy8WZOxSauIcZvy9CazXPZprkEhnGIExV4LFzbelG4T2DP7cvO9zmJXb481p3g5U0tWfahvh5EqZp9j3fxvKGcEYNA8CH3rFpYwltCxk_yKNkQFJvXcUOyLbu9t98HBvhcl2-vL-g61K7f9v_ZEvRuhJFbGNXRY4GZdvEuzsKacNcYOMPELptoEZpgeHvilfqPtIGhQJbl5f8m4etXfHlC29N7dAd3avkiqfE_4zpUGe9t8ZGonpZkzvBgsknK_g7pCwI8SstBKJJm6s9etbbmQJsHO1mwLdw", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItMCIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6OTg3NjU0MzIwOSwiZXhwIjo5ODc2NTQzMjEwLCJub25jZSI6IjE5NjQzNjk4ODYxMjY1NTY3ODA0OTA5OTEzMTMwNTA3MjQ3ODE0NTI2OTEzNTcwMjI4MzE2NDE3Mzc3OTY1MTA1NjgxNzk2MTczMDk4In0.BCN-S-x_rzfjdd3vXWi-uSwVJ1dzpMNNBrIFFG43-R5locy09OLf8kJvL_LXBsofLWlbQH9vmXmfK14yIMhU_4OwFE4egK01mAankyw-TME1pKeJxXVSc1E_50hHMWRYlOoik1kA5QK3ZydBYzYZvTI8tSPEk4BA_FDJVNuF0MZhtHe71-ZHv8anz2Q4ytHY2w0A3XygHlK1dry9IreUB3jsTPi5B4wodKbPCOH6E9xgZCq4s30OgvPav51hJQXQ6wR6xN0ERCMZmNJj7leXjGrwYMJjU0_SNgcCASmOkEK8DHdqcJkuF5ugbzlOADt42F2J6q4GijjO2sHhzndboA", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItMSIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6OTg3NjU0MzIwOSwiZXhwIjo5ODc2NTQzMjEwLCJub25jZSI6IjE5NjQzNjk4ODYxMjY1NTY3ODA0OTA5OTEzMTMwNTA3MjQ3ODE0NTI2OTEzNTcwMjI4MzE2NDE3Mzc3OTY1MTA1NjgxNzk2MTczMDk4In0.wzFIsFnCzlhOyDOaMPamxyd9mQgXSKlWoLJrhhaxqZTAbqzahMDD6xJd-8mERqzNAfKStzP0VyX3yOvKn5HzPME-ZsVtq6IAbeCIt6ZlDibsb0nq0nniIa4tMCkCHnThAge7e1NfFrRgeB3FzzCc5dMBsZEnJJbnnMpH0qKkLGM-sbslgzRnlCs1lXRxVb7KjzB4ALSq8GC8sazNsBtitBNwNUjloKD-YVz1wVgimjX1gQR5Kwy44suPLdrC9wIhOgwijsMkd2xh2xBzq_4W7nqgmlX2FaSs5lflrvA38ecbRu19tu9X2y93I5Ki8ht3648di2Qf4hYK4PG1hSbGtA", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItMiIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6OTg3NjU0MzIwOSwiZXhwIjo5ODc2NTQzMjEwLCJub25jZSI6IjE5NjQzNjk4ODYxMjY1NTY3ODA0OTA5OTEzMTMwNTA3MjQ3ODE0NTI2OTEzNTcwMjI4MzE2NDE3Mzc3OTY1MTA1NjgxNzk2MTczMDk4In0.OexmQ2rCjQwRZ6rr-6U1amIsY1JzlU5JNwKdbiCNnY37tHFoSH3Mgshr3R34eYuNF4OIG1F-a55m5cNf3-FF-tsDXw87QCVBlzlz4vTu0EloGnFSzYhcAb8U_5feVlsKBdWJpTKs1TIVhnNi-vosA_ObETnjT21LLURm_NiL3gCLwkqcMnvbmvB7Zkx46jK9rezw-F6yy9z5gja5WrCgcdLco3Um3y_Slaov6zvISckG-TYJ9qVy86hhYVZJkvRUtOwX7lKbz2z9vjFIEQMdFQOwtp81_NWqAmPn0PNVW1KQ_rMsmzXwUkVzMhI3Zaue9IBpaU42cLH6me4pS-58Dw", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItMyIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6OTg3NjU0MzIwOSwiZXhwIjo5ODc2NTQzMjEwLCJub25jZSI6IjE5NjQzNjk4ODYxMjY1NTY3ODA0OTA5OTEzMTMwNTA3MjQ3ODE0NTI2OTEzNTcwMjI4MzE2NDE3Mzc3OTY1MTA1NjgxNzk2MTczMDk4In0.YeXM8xecsIEkFVrZOmlygwj54LLnrEQ0JVFk7xComSCgc4_rPN6mX7uvHqbE-vSsPGiUX75NJLggxuzjGjyf8SHywy25jlvtewhdp_SrEoHJ22rs1PnhGh8XyXvul1-JAEQpV7_41-a8i2GPAGyweqhvpjEH2U6o41tCeZWzcDZ1XjFjfpp3v0YcmliXY5-vGrlj906B4m4Il4p6qnhloFAod2mNRwR-Vp7akz2wdYv5BnlkieTbl8grkuLXFdNuEIhUBWCA3lQY1WrAZRUQc74CVuZMQHufQmP95vVofLh6X7FNAyCmXwa6opvIQXzscyiKC-xlViUD-HPHysQHzg", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItNCIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6OTg3NjU0MzIwOSwiZXhwIjo5ODc2NTQzMjEwLCJub25jZSI6IjE5NjQzNjk4ODYxMjY1NTY3ODA0OTA5OTEzMTMwNTA3MjQ3ODE0NTI2OTEzNTcwMjI4MzE2NDE3Mzc3OTY1MTA1NjgxNzk2MTczMDk4In0.eS7g3uRq2Jg2jREfmnRZ2Yj7kMEyp82v3tERdY9OTCjL_bhzA5d_HxqnfdmklTvcWemC01KzMIzrjusVgs7YWnGaelc8qR9djBArj8gJRAamksem2SYSJ4dqO7wMBL9HJ9705vtuQesapNRpUHT8qj0aCa4pZwz-Ex-zJ98TKp_7vppsnvT9IP0GQuKHN6GMaBxErLnsF5lK7Ba9XaP2EAJMfc_8_gIDcO3kTpvo7VPLyN41Y1S7zTrmW4ncFzD5uPa-aQX4Crw93TxnQlAB5Zfv9Ox8pjLpi0usvjEHJ6A_fYi1SAalcqCF3keFqEBsbhSK-cHDawAd3Ki5ryABGg", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItNSIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6OTg3NjU0MzIwOSwiZXhwIjo5ODc2NTQzMjEwLCJub25jZSI6IjE5NjQzNjk4ODYxMjY1NTY3ODA0OTA5OTEzMTMwNTA3MjQ3ODE0NTI2OTEzNTcwMjI4MzE2NDE3Mzc3OTY1MTA1NjgxNzk2MTczMDk4In0.teQBBRCSW9o_j2MaxyLRmm1wdqK56p_IsZ3hj2SLrGMuXM2YiEv2DKJh3FL3HHn9ZgEdA2BKl5k0Y8BpUG3ebIIZD9sccTa8aX989q8lFIxrY4sIZhMjRxypHVu19iTtlDtIyCJmqOvhEjae0I19d9gx-Mqx4lFKyoFz5hnUBi0UwvCmttHu8tqNQCj2HKTNem-zy7kBZ8d7YpjhXSDEUm_vwBubJhETqIxfBPkOS-P3vFG-yQMGNeU240IFElII8rAPbpyDGY83sdQ-3sw9CniDpMEVlqJMqpmNjLSlwh83RcsDkV4SQXgpWAOY2_nF7IqA5Um4v0LovKnznUaTwA", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItNiIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6OTg3NjU0MzIwOSwiZXhwIjo5ODc2NTQzMjEwLCJub25jZSI6IjE5NjQzNjk4ODYxMjY1NTY3ODA0OTA5OTEzMTMwNTA3MjQ3ODE0NTI2OTEzNTcwMjI4MzE2NDE3Mzc3OTY1MTA1NjgxNzk2MTczMDk4In0.unkS5CT8dO_6K9S07aCn8CmaZJ1-MX9D1HyqDslSOG_ImHcJCB6OQOM7-xCgWT8ebOovxinCN77w2XsJpPXQbZEf4v8MDC8X7kJo7qqCmc1LOdlt-jcJEir8XThygl60-_HVMh93QISdmIFE07EEQENrSa_8OyQk_94glJlL2ng58g88U67WUgLHnyVvTlJ71Sfd3b1TKpuWuHTucncFIFNwX_6Oyl0bxFEQKOZpoNCpp1UThdMkNE-sg5Ec0-W0Dheyfxub74MAMDE_CILunAiELd3mEuOVwHr6RJkQre2U_UZsHT175pezfCxCM5ZA4PpsNZSSIkxS1c7KQDJyBA", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItNyIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6OTg3NjU0MzIwOSwiZXhwIjo5ODc2NTQzMjEwLCJub25jZSI6IjE5NjQzNjk4ODYxMjY1NTY3ODA0OTA5OTEzMTMwNTA3MjQ3ODE0NTI2OTEzNTcwMjI4MzE2NDE3Mzc3OTY1MTA1NjgxNzk2MTczMDk4In0.ple8-oCzCov_tvaK7hz7m4eE1RkQgpVk03-8Eh87XWJiZYjuD8zv4u0o6WREkHQzO9AIf5cGMlcyBPWer1680dVz46mvMeFvftxKihP31N5Bx5H56vIGNmjlIfwUECCj0iBIxq87Ixh5WTXkKd9bFMfgOeqcQniHDJQBSp0i-5UE_1Xxt1hALGCMEJxJ9HAhmGbYnXrfZ1zkUzlXndSQYm1kQMuqFs2TPoi5wMwV8vAi_zlOJvVQ3uAqCOQXJkDyogMwM2SOgX5JEP8GpfcVg9dAx9nY3j2fJ_DdvYuOrnZqyVjlkrEJsr80PqT0pw0cRE7gPrjMKDlJ6DXzRzb7pQ", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItOCIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6OTg3NjU0MzIwOSwiZXhwIjo5ODc2NTQzMjEwLCJub25jZSI6IjE5NjQzNjk4ODYxMjY1NTY3ODA0OTA5OTEzMTMwNTA3MjQ3ODE0NTI2OTEzNTcwMjI4MzE2NDE3Mzc3OTY1MTA1NjgxNzk2MTczMDk4In0.ajSatwHX207cTD747yFQhHaBLAwhAdyguL7nxEzhkydnik3e7hGxokThDMfKfxwnma3jS7q7b-tgGuv1le1euOtdq63Mhev59SA0gcIZoTo9cYhm-d6dBh8t_AOhNSwDG5_ztmAJvV8vt2WK6YA68sRszuTM5xejBC5oBcSRUJWDNYgnbVPNT8gTiFyk-67YBP-fFUrG9mvD5XwSw90cq2NpLXa0j4hXTS3XjXRavJ_5ryXwlijQg9NqDzmFsLJK2WqpWlEvOy2ui5u6PLwYLxotTM0qMzhTi--qB5VJqNPCg7S8Uw-cjQ-pnyPrgVVNIhxmO5K-mF6R7rnkHEJZJQ", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItOSIsImVtYWlsIjoidGVzdEBhcHRvc2xhYnMuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlhdCI6OTg3NjU0MzIwOSwiZXhwIjo5ODc2NTQzMjEwLCJub25jZSI6IjE5NjQzNjk4ODYxMjY1NTY3ODA0OTA5OTEzMTMwNTA3MjQ3ODE0NTI2OTEzNTcwMjI4MzE2NDE3Mzc3OTY1MTA1NjgxNzk2MTczMDk4In0.bGjpsD3NCEWk4uzbp0p507UrZYVAAB0-jTVFFlTO1ULWSL8W91AtMskIqGfSL0hPJY9qIZQ7-d8qns5T7Gy16lESV5GF3hiKHcOaMHzuA-D0TJXR366jBAGEloEx-hU_S4mXJHnRloigYBWcE9nEHv50ZqmiR7GHHJsGhNt5Zf06Nd3FlAi2PypK_QWYGgC7jeq8AYNhS0SKjaKDTClGWPscl4IAdggNlunXgIniAJeSneN1vrCXwlbjBFYkWZba3txvwo78C3VrSRl3v9p0bbW3Yp-l9eSfKIdzfICX8mmCf3qky7-I1jRyG6S2dzzHkhzOEhEilVRW8veLbZ0j_w", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItMTAiLCJlbWFpbCI6InRlc3RAYXB0b3NsYWJzLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJpYXQiOjk4NzY1NDMyMDksImV4cCI6OTg3NjU0MzIxMCwibm9uY2UiOiIxOTY0MzY5ODg2MTI2NTU2NzgwNDkwOTkxMzEzMDUwNzI0NzgxNDUyNjkxMzU3MDIyODMxNjQxNzM3Nzk2NTEwNTY4MTc5NjE3MzA5OCJ9.mn1OHr2l_mspJIWHhW_CZ2yPoYfU_suYrLS8wmPqcPaVPTtzh2ygTrwyqnw6SArjPRBYJZ3kjpteG5C5RLs5nRCcH3ZmHDokIMHOu7upbh8VXcPGEZftS2WHRIBMyFALUs0SUIz9fJqWOZmN3UO1OQ_uwRskLFidOkt2OxSIA9dR3wtjl9UmXctnDASJHl5y3i1Q3jTD_FF9qDiPdaPCvHjmOmzXNgrfl1xLLFUHjZg13favXA8SeyydLLfNh1TqUZIfXbav9p3Nys-8qrBh_O9XTxRptGwBnAZvQ9rMHnig7F-ZmEXjUR5XcXuyczmD-Ty7vHbYU2LLwwt8ePqiDQ", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItMTEiLCJlbWFpbCI6InRlc3RAYXB0b3NsYWJzLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJpYXQiOjk4NzY1NDMyMDksImV4cCI6OTg3NjU0MzIxMCwibm9uY2UiOiIxOTY0MzY5ODg2MTI2NTU2NzgwNDkwOTkxMzEzMDUwNzI0NzgxNDUyNjkxMzU3MDIyODMxNjQxNzM3Nzk2NTEwNTY4MTc5NjE3MzA5OCJ9.bqeIO4UJc4mRlRqB-fOAjUQSh74mwEprEAxAT9JFIfyRAUNeJwlzv5MwrF8Qde4s9eR-BMxvdMJKIaZHTrJZYLzHmQ80NfILB0XK_MDrHAQBxi_oq-drVGhAVAVs2-4BqdQL7ZIAp7SMZUu-2bNxgl6jOhLIH8cQPhtUc8kKYWxhrhOl6PNuYgAPjL1bD3An4XEranvLWTnqi8Cz411v8W7QwbebRqodkEghUYvvH3ASFoHSYYDocnQiuIC46grxZu-WRA6UO3ICwUc3wgAPm7n8iSINOb5wDbKnAXWb07s92bv00otydUVWpOprAcTyy_PvZPZ-8FWE_0WBXwA_Gg", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItMTIiLCJlbWFpbCI6InRlc3RAYXB0b3NsYWJzLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJpYXQiOjk4NzY1NDMyMDksImV4cCI6OTg3NjU0MzIxMCwibm9uY2UiOiIxOTY0MzY5ODg2MTI2NTU2NzgwNDkwOTkxMzEzMDUwNzI0NzgxNDUyNjkxMzU3MDIyODMxNjQxNzM3Nzk2NTEwNTY4MTc5NjE3MzA5OCJ9.jPpyBfxr-QgscJv0mxAn4UKMCI52mJwxF2sfHhH7Un_C9eGFLRzO52yO2znaHyV4eu_ggOFc_bXnMs5I2_OM949AryYHnEhXiaKQPiMex0ciieX0acgTuGBWss2g3xLaORJbbBDCFq48JeK-XY0oIX0F1Km_wszJ_bSTFF2PQxPmflsKjeFl6naidFLBl1qN4wZ4abUv5JeRXT5KCB3zvURPNa2Ub4nQWncG623L8vVU0_Nh5GD2aHvoDWKiOWWLU7QhWVxwRtxaQhtvkHDsUKFcdPFxns4AWxGsoyMNXEyonSAY4F4zcueaJLIwt6VZ1233Q2t_Igytq29jFGQh6w", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItMTMiLCJlbWFpbCI6InRlc3RAYXB0b3NsYWJzLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJpYXQiOjk4NzY1NDMyMDksImV4cCI6OTg3NjU0MzIxMCwibm9uY2UiOiIxOTY0MzY5ODg2MTI2NTU2NzgwNDkwOTkxMzEzMDUwNzI0NzgxNDUyNjkxMzU3MDIyODMxNjQxNzM3Nzk2NTEwNTY4MTc5NjE3MzA5OCJ9.p_ORBV4eqmA-ItGzAfwPGrMOMn8mLwxz8oriHhTzf-nDiikKT3LJKoGUT56zDr4HdovsllAP9ZnZuIh-aKhz-hjv7C1dpG2bH4iC3ZD1DEdL-yT3vzzan_vWJw_uj4iIVLm-_15sja7W2wiVzCaCOiy52_cSZWM6emFPqa4zEwL7sPLPfMtH-jtL505hH0Tf7JvPewqXKuKbLeV16hM64naF6F5fqRnWaJrW1AnIbz8QK6NLpNjZZrC8keBeeZOb5mhH5EVvKT2J4j2eBGSWrvhFRZMJRkaLGxFznpqxWTGGc1IvjBSIju66gn6vccklJ4Vn82Hl0RRMvyQQ8MDllw", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItMTQiLCJlbWFpbCI6InRlc3RAYXB0b3NsYWJzLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJpYXQiOjk4NzY1NDMyMDksImV4cCI6OTg3NjU0MzIxMCwibm9uY2UiOiIxOTY0MzY5ODg2MTI2NTU2NzgwNDkwOTkxMzEzMDUwNzI0NzgxNDUyNjkxMzU3MDIyODMxNjQxNzM3Nzk2NTEwNTY4MTc5NjE3MzA5OCJ9.eCdOPdCCtsR1xntyBZvg3bilQhxu8FnFwcAbvNf1WZUmV2Cv8hdT-8r40k5sBfGjnYO-MGaYdGh3YKN8n_wIt3IxExLUvkjGT_iTYo28SZlF7osyZ9IVhNZTEmQGh06Gu2yFcje-eV5Y8b-5TB0kCbsWkpCrM9CTaISyJaxAklFcYNqUBLE3Isd5H6d9fIzKJvPT4oh1RN3GXFIbZKlzpNjWRn3VwG-LMr24QtO095qYulc8XM77n6l-Y9XYsePHn-D-nP_zsOumk7yyWUHpl7Zx4HtKScSDxI9TA3fr6G-rdKvSimIgw73Wyih3C4ivL-lHrLVWWKsWRpdiEe3Ikg", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItMTUiLCJlbWFpbCI6InRlc3RAYXB0b3NsYWJzLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJpYXQiOjk4NzY1NDMyMDksImV4cCI6OTg3NjU0MzIxMCwibm9uY2UiOiIxOTY0MzY5ODg2MTI2NTU2NzgwNDkwOTkxMzEzMDUwNzI0NzgxNDUyNjkxMzU3MDIyODMxNjQxNzM3Nzk2NTEwNTY4MTc5NjE3MzA5OCJ9.OHNr8zctY6ZZum9ULjjSBqDjq6aDPLDsHh3u08oY0vWrHAz9V-a_4sJ5zQJvJTFhoPwihPaPPW7sGjLEA1bwqIZlH4iIcq-d0-uEcsTiRpt5M1-U7Ie-tuQAuQedwcMGS5WYL-Ky7HFQy4Ew3byw-ZOWoJw7SAWa1JBF9s6gzY_Is9dUciFiGKvLznJS_IApJBhBKn3-dxnjnA1z-US6qiebKZL_FBgALVxRBoVqfSKsXo2CXShFP6IAZ8CCjGS8xbPBxXLim9WK9zrAF4oNJatVhpAx9KqjjfhkGT146aIWMtuSakuLdmn5moYPkR9NeW_cqFv-NQ_0EW260EO14Q", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItMTYiLCJlbWFpbCI6InRlc3RAYXB0b3NsYWJzLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJpYXQiOjk4NzY1NDMyMDksImV4cCI6OTg3NjU0MzIxMCwibm9uY2UiOiIxOTY0MzY5ODg2MTI2NTU2NzgwNDkwOTkxMzEzMDUwNzI0NzgxNDUyNjkxMzU3MDIyODMxNjQxNzM3Nzk2NTEwNTY4MTc5NjE3MzA5OCJ9.RQ8KXbFwpRluLWOIpCxu9K5PQqrdT6zF70JiZZMHMUDCxM0COeupGQ5WyQ8-eTobADcYv7yT4o2sjMS3CIUKk0yxJ9mQhhqFatWGlKHym9arLlvGijxyD5wGnYlqiwIwBe-1LNq6bUyX0th--TsXUG2QY7qeXRnqylUHmdI6Blq8Pa87yb1qC-D8tHUVqGnWDfgGbSzkGoyu4PUklu2MiQfU0eZJRvgBBxO-CWL8-Gcll9kINDr10_2tDkwCNPgyyj5YsYGAT0qCwVxWxoR0b4QGiPynd4OOaXYRHJ0pWLeYv9UUXp3ZcjAKpzX9awPxu9XW1XQXG9LiTvJX55Sueg", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItMTciLCJlbWFpbCI6InRlc3RAYXB0b3NsYWJzLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJpYXQiOjk4NzY1NDMyMDksImV4cCI6OTg3NjU0MzIxMCwibm9uY2UiOiIxOTY0MzY5ODg2MTI2NTU2NzgwNDkwOTkxMzEzMDUwNzI0NzgxNDUyNjkxMzU3MDIyODMxNjQxNzM3Nzk2NTEwNTY4MTc5NjE3MzA5OCJ9.gXuZn_HzgoQVo-E1w_hHkj7VZx3PoWF6bB5HVUBKLwRRW0R6kd9y5fNow1op_vGqX7IjxqOTc0yRhKmWRwMp6IFWGbUfhw7B9mYABD8PBBGEZFTSGqsUqOOn5G_6gmXmcKrkpPBgAdeu9KZI00e_aks5Nm38Eo9mtpA-NAxcFVaB7H5czX5It3QMLQVZm8nRDT6utz6yKDOQ8jYO5Mfui3E3q1FQLAPaU7mH84fkbfMUbm6jiabebHE9DPSogfz20_TF_LTRr_dVtIRzdHOZifdX8RWU2ZQptFQyt_H-0zO9xudvLLZW_E2jOzl0sLRhVr4zGHIqXE7pcjauNiTc6w", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItMTgiLCJlbWFpbCI6InRlc3RAYXB0b3NsYWJzLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJpYXQiOjk4NzY1NDMyMDksImV4cCI6OTg3NjU0MzIxMCwibm9uY2UiOiIxOTY0MzY5ODg2MTI2NTU2NzgwNDkwOTkxMzEzMDUwNzI0NzgxNDUyNjkxMzU3MDIyODMxNjQxNzM3Nzk2NTEwNTY4MTc5NjE3MzA5OCJ9.m1FwlGIn8Z107Z6hCFqOZPlZXIQ8xLZbH7wyJ_Dlu7bTSM_x7mP-Zpq6EPcl4fiKM0R5BOEp30PIdoi7epx2NecgtG0ZGD6kFIfAf1WTPOWFnJaDNLAhdPrwyPy1IlMo32azw1n2v5wMyS2136drEEpZbK0FlqwwdriBfex8LPfK52UB3OiYhfD1bgcF3Vmk-KbE_I6NV3lJ9bIXzaO5e6oNQNTuE4akosvjvV2eyyj3cGgjjhz6JLga8RG2l09Kp1QPkftKfcxb7zeLqGrGCYy3pzngnd2NSr-3bSib1DqqinVdIIAGD_TKSRQbL4-C_cPYX6mzwHrolt4RgLCX6g", + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0LmZlZGVyYXRlZC5vaWRjLnByb3ZpZGVyIiwiYXVkIjoidGVzdC1rZXlsZXNzLWRhcHAiLCJzdWIiOiJ0ZXN0LXVzZXItMTkiLCJlbWFpbCI6InRlc3RAYXB0b3NsYWJzLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJpYXQiOjk4NzY1NDMyMDksImV4cCI6OTg3NjU0MzIxMCwibm9uY2UiOiIxOTY0MzY5ODg2MTI2NTU2NzgwNDkwOTkxMzEzMDUwNzI0NzgxNDUyNjkxMzU3MDIyODMxNjQxNzM3Nzk2NTEwNTY4MTc5NjE3MzA5OCJ9.xYHVyi1BCZB5szBOS4xbDtORAreaTiDmYfR8l3mmApQgLuAzkv4fPGuClLEitD9rrh1hVQ1tgYqk05cXKA_al6vEa8maxduPd-Q41Yp4Ji3-CU-MgQYqtZNyWPxv9dvMxCat_BCs8z1tZ9g1d7fLGs2G5-IgDhlNhmsmCanLxUUDijPtjvA6xZfRqR4lzS2MtyzPO7dMS7YZFV47O2Rl4CHhDOBPHqplJ1I_T26zurvuZWxT3vOy4qm863dPqRli4UNMTAxGfUB2xn8j36SyhqYzfYuOXjHnTgHsxP3yHY2vg6ttnscoU-Ue4HN6ICeAgnUUXdDpoaPan4qO1OLunA", ]; const KEYLESS_TEST_TIMEOUT = 12000; @@ -112,12 +121,18 @@ describe("keyless api", () => { ); test("submitting a keyless txn using an outdated JWK should error with meaningful message", async () => { - // This deserializes a keyless account derived from a JWT with a kid that is no longer valid. - const account = KeylessAccount.fromBytes( - Hex.fromHexInput( - "0xca51c631dc87ed1f1363920972d4e05bbef8d5f332a0921185715b2bef0f3036da0565794a68624763694f694a53557a49314e694973496e523563434936496b705856434973496d74705a434936496e526c63335174636e4e684d694a392e65794a7063334d694f694a305a584e304c6d39705a474d7563484a76646d6c6b5a5849694c434a68645751694f694a305a584e304c57746c6557786c63334d745a47467763434973496e4e3159694936496e526c6333517464584e6c63694973496d567459576c73496a6f696447567a644542686348527663327868596e4d7559323974496977695a57316861577866646d567961575a705a5751694f6e527964575573496d6c68644349364f5467334e6a55304d7a49774f5377695a586877496a6f354f4463324e54517a4d6a45774c434a756232356a5a534936496a63774f5455794e44497a4d7a4d354e6a51304e5463794e6a63354d7a51334d6a4d334e6a67774f44417a4d444d7a4d6a51304e6a49344d6a45784f5445334e5459304d446b304e5441774f546b314d546b334f4445774e5445354d5441784f4463784d54676966512e526d417a3365455f6156786a4d47464874744b6b557a507677764451755664474667585633566968685937613242386a756b5f50772d4e714c4545674c4473425f5668316a446f507953766f6769454477485a3566546f716b396272496d64666d414377323770722d2d4d51366b6e366e306b32584f506d4d716a51374b454d4d3433526637734b5f39542d67756f7666304956523434734a44716e434a616e5842645a4b35326a4e52766a327a6d6b4d79705659585148417a356a764a6c4351636e5468304d70496d39494f67527a6a4b546b3061783857723949447a7a775f5f6c6a6a303336636c696d57427a68474b4b7739614b49656b373055673668323630346f49384342526c784f4b696d7732344e58494f5f326a5142524d666554575f68496d3971337051314f4d4c2d6637504d47644141795647785f73454d30777759706344666a4245674b315f526752414e5267037375620000000000000000000000000000000000000000000000000000000000000000201111111111111111111111111111111111111111111111111111111111111111443f716700000000000000000000000000000000000000000000000000000000000000000000000097f61c10a645a6429d48edc38939035ce591d90c4facdb0c56e749c1d90b5d85dafda25db344f6ef2618ce9164c968448426feaab0d65cf492923f3136d9c10c484016524e358764ff956f97a51d0e01df330f6619408dd1bbe860211bbcd888168b197e055d23873115a0f3597630db1f03499b427991587aab0e12608a541c809698000000000000000100408ee4b0e9ab9c7b1c87b5ac173f83ccacc9d36a5696a36d1c536906c56ab7db8c3c75f039f70caf483a898b6b34b87559a29e725f4b3331e31134064884b2b80c00", - ).toUint8Array(), - ); + const account = KeylessAccount.create({ + ephemeralKeyPair: EPHEMERAL_KEY_PAIR, + jwt: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhMiJ9.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci0wIiwiZW1haWwiOiJ0ZXN0QGFwdG9zbGFicy5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiaWF0Ijo5ODc2NTQzMjA5LCJleHAiOjk4NzY1NDMyMTAsIm5vbmNlIjoiMTk2NDM2OTg4NjEyNjU1Njc4MDQ5MDk5MTMxMzA1MDcyNDc4MTQ1MjY5MTM1NzAyMjgzMTY0MTczNzc5NjUxMDU2ODE3OTYxNzMwOTgifQ.v_fayuJ6_t76mX3SchhJNwkUDDkb7RyQug2SNS0PlIYCkpaHwHmtCakPJmuBS17RKCC0Hv2urz4MK54xYaVzkJUaINH9RZ31U5iqXZLDveVEUbbfT34vaIeXjuKIGOYnf1GDqZIBGKLN_oDN2yASlQMjs4YSQQdC-JRcHYsSmm9yDjqbfSOMj44A0Vce2PvA7vFVXCYrjOOqk0yxm3e-iXm1YvbOeAMBTplVwOuGXA2qmJWaJsmyIhn2pK1RDp1nFkDA0bxvsxKLZOuJYrz3k-ENOIiZDEkP9bYFMFN2bQ1pNaJDt15XpNJwNu02Xg6khKp5DxPcdXJidli8T2_T3Q", + proof: new ZeroKnowledgeSig({ + proof: new ZkProof( + new Groth16Zkp({ a: new Uint8Array(32), b: new Uint8Array(64), c: new Uint8Array(32) }), + ZkpVariant.Groth16, + ), + expHorizonSecs: 100000, + }), + pepper: new Uint8Array(31), + }); const recipient = Account.generate(); await expect(simpleCoinTransactionHelper(aptos, account, recipient)).rejects.toThrow( "JWK with kid 'test-rsa2' for issuer 'test.oidc.provider' not found.", diff --git a/tests/e2e/transaction/helper.ts b/tests/e2e/transaction/helper.ts index db96aee90..ba02a4f6e 100644 --- a/tests/e2e/transaction/helper.ts +++ b/tests/e2e/transaction/helper.ts @@ -24,7 +24,7 @@ import { getAptosClient } from "../helper"; export const EPHEMERAL_KEY_PAIR = new EphemeralKeyPair({ privateKey: new Ed25519PrivateKey("ed25519-priv-0x1111111111111111111111111111111111111111111111111111111111111111"), - expiryDateSecs: 1735475012, // Expires Sunday, December 29, 2024 12:23:32 PM GMT + expiryDateSecs: 9876543210, // Expires Friday, December 22, 2282 8:13:30 PM GMT blinder: new Uint8Array(31), }); diff --git a/tests/e2e/transaction/transactionBuilder.test.ts b/tests/e2e/transaction/transactionBuilder.test.ts index c6c51b087..e845e89a2 100644 --- a/tests/e2e/transaction/transactionBuilder.test.ts +++ b/tests/e2e/transaction/transactionBuilder.test.ts @@ -418,7 +418,7 @@ describe("transaction builder", () => { test("it generates a keyless signed raw transaction for simulation", async () => { const jwt = - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci0xMDAwIiwiZW1haWwiOiJ0ZXN0QGFwdG9zbGFicy5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiaWF0IjoxNzI1NDc1MTEyLCJleHAiOjI3MDAwMDAwMDAsIm5vbmNlIjoiNzA5NTI0MjMzMzk2NDQ1NzI2NzkzNDcyMzc2ODA4MDMwMzMyNDQ2MjgyMTE5MTc1NjQwOTQ1MDA5OTUxOTc4MTA1MTkxMDE4NzExOCJ9.vNtz77nUUq_E0LEKqqpPEkF6LTTNk9UomfPlfbQ41-RjSxTHU9ht1df1PFrCMzO_4k0fo8JZt7P5e4qvmxQjZlA66wO9e9L0j29UlL8ZKSkZko_VLGh3hvUXL1dMviQEe4MrXR515b-m4krAPRP6n6bagksFnooA9pPOXW5WTIsjgRfQefLP9VDyxJ1Br0pAGq9LYkrXWGDegjiv35MYr6PM3ao7yq7x-wAvF3wIqjTxnmuaAln5itThuKG8kQ1IsbOJP1G_EyyHszH6Xd7TXPwbcFLBqs-az1zjvTSA1YlsdgbT2m5dTt8YaThm5ZX6cmlOHVvhfSM-CZlAWy5JOg"; + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3QtcnNhIn0.eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhdWQiOiJ0ZXN0LWtleWxlc3MtZGFwcCIsInN1YiI6InRlc3QtdXNlci0xMDAwIiwiZW1haWwiOiJ0ZXN0QGFwdG9zbGFicy5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiaWF0Ijo5ODc2NTQzMjA5LCJleHAiOjk4NzY1NDMyMTAsIm5vbmNlIjoiMTk2NDM2OTg4NjEyNjU1Njc4MDQ5MDk5MTMxMzA1MDcyNDc4MTQ1MjY5MTM1NzAyMjgzMTY0MTczNzc5NjUxMDU2ODE3OTYxNzMwOTgifQ.SpD0esGrw23ytFOMtp5Z23ysyh5QWeTfvsxgyQyUCa6L0hVgGiQ53n3AfdqrJntJ2vpHz8ixnvcOewa-eIWeSrnb6mGszoFnGnpS8R4dl0ZFsRzBSiO0jDeyZtRzKKdTO4uGiTHIHHDOWLjwHDOevpyXHmADjYuXnT8IdKyUk6f2ZmjRh0nMHsyo2bGtaTs4AekWP9yNxUqb1tv4-9OoA64YdKmmWQT5u_nTot-LbSzbief8hwXEtttKGMHJPzBhqYvrnMZiQmys-p1jmHkYfPHouqPZNdkGeIfDZXY88C8LVNASrCo_l9jIj78RM06CRmxJ3oo8hTABpIEkQmnQqA"; const ephemeralKeyPair = EPHEMERAL_KEY_PAIR; const pepper = await aptos.getPepper({ jwt, ephemeralKeyPair }); const publicKey = KeylessPublicKey.fromJwtAndPepper({ jwt, pepper }); From 8c9e01b879d7f14ff285668e1e3efe9655d89667 Mon Sep 17 00:00:00 2001 From: Oliver He Date: Thu, 9 Jan 2025 05:39:29 +0700 Subject: [PATCH 2/2] Add AccountUtils which allows for general serialization of the account classes (#571) * Add serialization to the account classes * Move serialization of accounts to accountUtils * add changelog * Make public keys required in multikey constructor * update cl * Use namespace instead of class * Update error log --- CHANGELOG.md | 2 + src/account/AbstractKeylessAccount.ts | 10 +- src/account/Account.ts | 11 +- src/account/AccountUtils.ts | 216 ++++++++++++++++++ src/account/FederatedKeylessAccount.ts | 9 +- src/account/KeylessAccount.ts | 2 +- src/account/MultiKeyAccount.ts | 51 ++++- src/account/SingleKeyAccount.ts | 41 +++- src/account/index.ts | 1 + src/account/utils.ts | 16 ++ src/api/transaction.ts | 4 +- src/bcs/deserializer.ts | 8 +- src/core/crypto/multiKey.ts | 2 +- src/core/crypto/singleKey.ts | 6 +- src/internal/transactionSubmission.ts | 4 +- .../transaction/transactionSubmission.test.ts | 11 + tests/unit/accountSerialization.test.ts | 120 ++++++++++ 17 files changed, 476 insertions(+), 38 deletions(-) create mode 100644 src/account/AccountUtils.ts create mode 100644 src/account/utils.ts create mode 100644 tests/unit/accountSerialization.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index a463fe57e..cf9785dbb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ All notable changes to the Aptos TypeScript SDK will be captured in this file. T # Unreleased +- Add `AccountUtils` class to help with account serialization and deserialization +- Add `SingleKeySigner` interface which adds the ability to get the `AnyPublicKey` from a `SingleKeyAccount` - We now throw an error earlier when you try to use the faucet with testnet or mainnet, rather than letting the call happen and then fail later. # 1.33.1 (2024-11-28) diff --git a/src/account/AbstractKeylessAccount.ts b/src/account/AbstractKeylessAccount.ts index a97999630..13c0d875b 100644 --- a/src/account/AbstractKeylessAccount.ts +++ b/src/account/AbstractKeylessAccount.ts @@ -29,6 +29,7 @@ import { FederatedKeylessPublicKey } from "../core/crypto/federatedKeyless"; import { Account } from "./Account"; import { AptosConfig } from "../api/aptosConfig"; import { KeylessError, KeylessErrorType } from "../errors"; +import type { SingleKeySigner } from "./SingleKeyAccount"; /** * An interface which defines if an Account utilizes Keyless signing. @@ -47,7 +48,7 @@ export function isKeylessSigner(obj: any): obj is KeylessSigner { * @group Implementation * @category Account (On-Chain Model) */ -export abstract class AbstractKeylessAccount extends Serializable implements KeylessSigner { +export abstract class AbstractKeylessAccount extends Serializable implements KeylessSigner, SingleKeySigner { static readonly PEPPER_LENGTH: number = 31; /** @@ -120,7 +121,7 @@ export abstract class AbstractKeylessAccount extends Serializable implements Key * @group Implementation * @category Account (On-Chain Model) */ - readonly signingScheme: SigningScheme; + readonly signingScheme: SigningScheme = SigningScheme.SingleKey; /** * The JWT token used to derive the account @@ -211,7 +212,6 @@ export abstract class AbstractKeylessAccount extends Serializable implements Key // Note, this is purposely not awaited to be non-blocking. The caller should await on the proofFetchCallback. this.init(proof); } - this.signingScheme = SigningScheme.SingleKey; const pepperBytes = Hex.fromHexInput(pepper).toUint8Array(); if (pepperBytes.length !== AbstractKeylessAccount.PEPPER_LENGTH) { throw new Error(`Pepper length in bytes should be ${AbstractKeylessAccount.PEPPER_LENGTH}`); @@ -225,6 +225,10 @@ export abstract class AbstractKeylessAccount extends Serializable implements Key } } + getAnyPublicKey(): AnyPublicKey { + return new AnyPublicKey(this.publicKey); + } + /** * This initializes the asynchronous proof fetch * @return Emits whether the proof succeeds or fails, but has no return. diff --git a/src/account/Account.ts b/src/account/Account.ts index bfb94adb5..67166b73e 100644 --- a/src/account/Account.ts +++ b/src/account/Account.ts @@ -2,7 +2,7 @@ import type { AccountAuthenticator } from "../transactions/authenticator/account import { HexInput, SigningScheme, SigningSchemeInput } from "../types"; import type { AccountAddress, AccountAddressInput } from "../core/accountAddress"; import { AuthenticationKey } from "../core/authenticationKey"; -import { AccountPublicKey, Ed25519PrivateKey, PrivateKey, Signature, VerifySignatureArgs } from "../core/crypto"; +import { AccountPublicKey, Ed25519PrivateKey, PrivateKeyInput, Signature, VerifySignatureArgs } from "../core/crypto"; import { Ed25519Account } from "./Ed25519Account"; import { SingleKeyAccount } from "./SingleKeyAccount"; import { AnyRawTransaction } from "../transactions/types"; @@ -50,7 +50,7 @@ export interface CreateEd25519SingleKeyAccountFromPrivateKeyArgs { * @category Account (On-Chain Model) */ export interface CreateSingleKeyAccountFromPrivateKeyArgs { - privateKey: Exclude; + privateKey: PrivateKeyInput; address?: AccountAddressInput; legacy?: false; } @@ -65,7 +65,7 @@ export interface CreateSingleKeyAccountFromPrivateKeyArgs { * @category Account (On-Chain Model) */ export interface CreateAccountFromPrivateKeyArgs { - privateKey: PrivateKey; + privateKey: PrivateKeyInput; address?: AccountAddressInput; legacy?: boolean; } @@ -206,10 +206,9 @@ export abstract class Account { * @category Account (On-Chain Model) */ static fromPrivateKey(args: CreateEd25519AccountFromPrivateKeyArgs): Ed25519Account; - static fromPrivateKey(args: CreateEd25519SingleKeyAccountFromPrivateKeyArgs): SingleKeyAccount; static fromPrivateKey(args: CreateSingleKeyAccountFromPrivateKeyArgs): SingleKeyAccount; - static fromPrivateKey(args: CreateAccountFromPrivateKeyArgs): Account; - static fromPrivateKey(args: CreateAccountFromPrivateKeyArgs) { + static fromPrivateKey(args: CreateAccountFromPrivateKeyArgs): SingleKeyAccount; + static fromPrivateKey(args: CreateAccountFromPrivateKeyArgs): Ed25519Account | SingleKeyAccount { const { privateKey, address, legacy = true } = args; if (privateKey instanceof Ed25519PrivateKey && legacy) { return new Ed25519Account({ diff --git a/src/account/AccountUtils.ts b/src/account/AccountUtils.ts new file mode 100644 index 000000000..2995ef5c6 --- /dev/null +++ b/src/account/AccountUtils.ts @@ -0,0 +1,216 @@ +import { Deserializer, Serializer } from "../bcs"; +import { AnyPublicKeyVariant, HexInput, SigningScheme } from "../types"; +import { MultiKeyAccount } from "./MultiKeyAccount"; +import { Account } from "./Account"; +import { Ed25519Account } from "./Ed25519Account"; +import { isSingleKeySigner, SingleKeyAccount, SingleKeySignerOrLegacyEd25519Account } from "./SingleKeyAccount"; +import { KeylessAccount } from "./KeylessAccount"; +import { FederatedKeylessAccount } from "./FederatedKeylessAccount"; +import { AbstractKeylessAccount } from "./AbstractKeylessAccount"; +import { + AccountAddress, + Ed25519PrivateKey, + getIssAudAndUidVal, + Hex, + MultiKey, + Secp256k1PrivateKey, + ZeroKnowledgeSig, +} from "../core"; +import { deserializeSchemeAndAddress } from "./utils"; +import { EphemeralKeyPair } from "./EphemeralKeyPair"; + +function serializeKeylessAccountCommon(account: AbstractKeylessAccount, serializer: Serializer): void { + serializer.serializeStr(account.jwt); + serializer.serializeStr(account.uidKey); + serializer.serializeFixedBytes(account.pepper); + account.ephemeralKeyPair.serialize(serializer); + if (account.proof === undefined) { + throw new Error("Cannot serialize - proof undefined"); + } + account.proof.serialize(serializer); + serializer.serializeOption(account.verificationKeyHash, 32); +} + +function deserializeKeylessAccountCommon(deserializer: Deserializer): { + jwt: string; + uidKey: string; + pepper: Uint8Array; + ephemeralKeyPair: EphemeralKeyPair; + proof: ZeroKnowledgeSig; + verificationKeyHash?: Uint8Array; +} { + const jwt = deserializer.deserializeStr(); + const uidKey = deserializer.deserializeStr(); + const pepper = deserializer.deserializeFixedBytes(31); + const ephemeralKeyPair = EphemeralKeyPair.deserialize(deserializer); + const proof = ZeroKnowledgeSig.deserialize(deserializer); + const verificationKeyHash = deserializer.deserializeOption("fixedBytes", 32); + return { jwt, uidKey, pepper, ephemeralKeyPair, proof, verificationKeyHash }; +} + +/** + * Utility functions for working with accounts. + */ +export namespace AccountUtils { + export function toBytes(account: Account): Uint8Array { + const serializer = new Serializer(); + serializer.serializeU32AsUleb128(account.signingScheme); + account.accountAddress.serialize(serializer); + switch (account.signingScheme) { + case SigningScheme.Ed25519: + (account as Ed25519Account).privateKey.serialize(serializer); + return serializer.toUint8Array(); + case SigningScheme.SingleKey: { + if (!isSingleKeySigner(account)) { + throw new Error("Account is not a SingleKeySigner"); + } + const anyPublicKey = account.getAnyPublicKey(); + serializer.serializeU32AsUleb128(anyPublicKey.variant); + switch (anyPublicKey.variant) { + case AnyPublicKeyVariant.Keyless: { + const keylessAccount = account as KeylessAccount; + serializeKeylessAccountCommon(keylessAccount, serializer); + return serializer.toUint8Array(); + } + case AnyPublicKeyVariant.FederatedKeyless: { + const federatedKeylessAccount = account as FederatedKeylessAccount; + serializeKeylessAccountCommon(federatedKeylessAccount, serializer); + federatedKeylessAccount.publicKey.jwkAddress.serialize(serializer); + serializer.serializeBool(federatedKeylessAccount.audless); + return serializer.toUint8Array(); + } + case AnyPublicKeyVariant.Secp256k1: + case AnyPublicKeyVariant.Ed25519: { + const singleKeyAccount = account as SingleKeyAccount; + singleKeyAccount.privateKey.serialize(serializer); + return serializer.toUint8Array(); + } + default: { + throw new Error(`Invalid public key variant: ${anyPublicKey.variant}`); + } + } + } + case SigningScheme.MultiKey: { + const multiKeyAccount = account as MultiKeyAccount; + multiKeyAccount.publicKey.serialize(serializer); + serializer.serializeU32AsUleb128(multiKeyAccount.signers.length); + multiKeyAccount.signers.forEach((signer) => { + serializer.serializeFixedBytes(toBytes(signer)); + }); + return serializer.toUint8Array(); + } + default: + throw new Error(`Deserialization of Account failed: invalid signingScheme value ${account.signingScheme}`); + } + } + + export function toHexStringWithoutPrefix(account: Account): string { + return Hex.hexInputToStringWithoutPrefix(toBytes(account)); + } + + export function toHexString(account: Account): string { + return Hex.hexInputToString(toBytes(account)); + } + + export function deserialize(deserializer: Deserializer): Account { + const { address, signingScheme } = deserializeSchemeAndAddress(deserializer); + switch (signingScheme) { + case SigningScheme.Ed25519: { + const privateKey = Ed25519PrivateKey.deserialize(deserializer); + return new Ed25519Account({ privateKey, address }); + } + case SigningScheme.SingleKey: { + const variantIndex = deserializer.deserializeUleb128AsU32(); + switch (variantIndex) { + case AnyPublicKeyVariant.Ed25519: { + const privateKey = Ed25519PrivateKey.deserialize(deserializer); + return new SingleKeyAccount({ privateKey, address }); + } + case AnyPublicKeyVariant.Secp256k1: { + const privateKey = Secp256k1PrivateKey.deserialize(deserializer); + return new SingleKeyAccount({ privateKey, address }); + } + case AnyPublicKeyVariant.Keyless: { + const keylessComponents = deserializeKeylessAccountCommon(deserializer); + const jwtClaims = getIssAudAndUidVal(keylessComponents); + return new KeylessAccount({ ...keylessComponents, ...jwtClaims }); + } + case AnyPublicKeyVariant.FederatedKeyless: { + const keylessComponents = deserializeKeylessAccountCommon(deserializer); + const jwkAddress = AccountAddress.deserialize(deserializer); + const audless = deserializer.deserializeBool(); + const jwtClaims = getIssAudAndUidVal(keylessComponents); + return new FederatedKeylessAccount({ ...keylessComponents, ...jwtClaims, jwkAddress, audless }); + } + default: + throw new Error(`Unsupported public key variant ${variantIndex}`); + } + } + case SigningScheme.MultiKey: { + const multiKey = MultiKey.deserialize(deserializer); + const length = deserializer.deserializeUleb128AsU32(); + const signers = new Array(); + for (let i = 0; i < length; i += 1) { + const signer = deserialize(deserializer); + if (!isSingleKeySigner(signer) && !(signer instanceof Ed25519Account)) { + throw new Error( + "Deserialization of MultiKeyAccount failed. Signer is not a SingleKeySigner or Ed25519Account", + ); + } + signers.push(signer); + } + return new MultiKeyAccount({ multiKey, signers, address }); + } + default: + throw new Error(`Deserialization of Account failed: invalid signingScheme value ${signingScheme}`); + } + } + + export function keylessAccountFromHex(hex: HexInput): KeylessAccount { + const account = fromHex(hex); + if (!(account instanceof KeylessAccount)) { + throw new Error("Deserialization of KeylessAccount failed"); + } + return account; + } + + export function federatedKeylessAccountFromHex(hex: HexInput): FederatedKeylessAccount { + const account = fromHex(hex); + if (!(account instanceof FederatedKeylessAccount)) { + throw new Error("Deserialization of FederatedKeylessAccount failed"); + } + return account; + } + + export function multiKeyAccountFromHex(hex: HexInput): MultiKeyAccount { + const account = fromHex(hex); + if (!(account instanceof MultiKeyAccount)) { + throw new Error("Deserialization of MultiKeyAccount failed"); + } + return account; + } + + export function singleKeyAccountFromHex(hex: HexInput): SingleKeyAccount { + const account = fromHex(hex); + if (!(account instanceof SingleKeyAccount)) { + throw new Error("Deserialization of SingleKeyAccount failed"); + } + return account; + } + + export function ed25519AccountFromHex(hex: HexInput): Ed25519Account { + const account = fromHex(hex); + if (!(account instanceof Ed25519Account)) { + throw new Error("Deserialization of Ed25519Account failed"); + } + return account; + } + + export function fromHex(hex: HexInput): Account { + return deserialize(Deserializer.fromHex(hex)); + } + + export function fromBytes(bytes: Uint8Array): Account { + return fromHex(bytes); + } +} diff --git a/src/account/FederatedKeylessAccount.ts b/src/account/FederatedKeylessAccount.ts index 6f3ad95c2..68c5f79b7 100644 --- a/src/account/FederatedKeylessAccount.ts +++ b/src/account/FederatedKeylessAccount.ts @@ -9,7 +9,6 @@ import { EphemeralKeyPair } from "./EphemeralKeyPair"; import { Deserializer, Serializer } from "../bcs"; import { FederatedKeylessPublicKey } from "../core/crypto/federatedKeyless"; import { AbstractKeylessAccount, ProofFetchCallback } from "./AbstractKeylessAccount"; -import { Hex } from "../core"; /** * Account implementation for the FederatedKeyless authentication scheme. @@ -32,6 +31,8 @@ export class FederatedKeylessAccount extends AbstractKeylessAccount { */ readonly publicKey: FederatedKeylessPublicKey; + readonly audless: boolean; + /** * Use the static generator `FederatedKeylessAccount.create(...)` instead. * Creates a KeylessAccount instance using the provided parameters. @@ -46,7 +47,7 @@ export class FederatedKeylessAccount extends AbstractKeylessAccount { * @param args.uidKey - Optional key for user identification, defaults to "sub". * @param args.proofFetchCallback - Optional callback function for fetching proof. */ - private constructor(args: { + constructor(args: { address?: AccountAddress; ephemeralKeyPair: EphemeralKeyPair; iss: string; @@ -59,10 +60,12 @@ export class FederatedKeylessAccount extends AbstractKeylessAccount { proofFetchCallback?: ProofFetchCallback; jwt: string; verificationKeyHash?: HexInput; + audless?: boolean; }) { const publicKey = FederatedKeylessPublicKey.create(args); super({ publicKey, ...args }); this.publicKey = publicKey; + this.audless = args.audless ?? false; } /** @@ -110,7 +113,7 @@ export class FederatedKeylessAccount extends AbstractKeylessAccount { * @returns */ static fromBytes(bytes: HexInput): FederatedKeylessAccount { - return FederatedKeylessAccount.deserialize(new Deserializer(Hex.hexInputToUint8Array(bytes))); + return FederatedKeylessAccount.deserialize(Deserializer.fromHex(bytes)); } /** diff --git a/src/account/KeylessAccount.ts b/src/account/KeylessAccount.ts index aef906844..946708a1b 100644 --- a/src/account/KeylessAccount.ts +++ b/src/account/KeylessAccount.ts @@ -51,7 +51,7 @@ export class KeylessAccount extends AbstractKeylessAccount { * @group Implementation * @category Account (On-Chain Model) */ - private constructor(args: { + constructor(args: { address?: AccountAddress; ephemeralKeyPair: EphemeralKeyPair; iss: string; diff --git a/src/account/MultiKeyAccount.ts b/src/account/MultiKeyAccount.ts index 529792e39..27cc3e043 100644 --- a/src/account/MultiKeyAccount.ts +++ b/src/account/MultiKeyAccount.ts @@ -1,7 +1,7 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -import { Account } from "./Account"; +import type { Account } from "./Account"; import { MultiKey, MultiKeySignature, PublicKey } from "../core/crypto"; import { AccountAddress, AccountAddressInput } from "../core/accountAddress"; import { HexInput, SigningScheme } from "../types"; @@ -9,6 +9,8 @@ import { AccountAuthenticatorMultiKey } from "../transactions/authenticator/acco import { AnyRawTransaction } from "../transactions/types"; import { AbstractKeylessAccount, KeylessSigner } from "./AbstractKeylessAccount"; import { AptosConfig } from "../api/aptosConfig"; +import { SingleKeyAccount, SingleKeySigner, SingleKeySignerOrLegacyEd25519Account } from "./SingleKeyAccount"; +import { Ed25519Account } from "./Ed25519Account"; /** * Arguments required to verify a multi-key signature against a given message. @@ -53,7 +55,7 @@ export class MultiKeyAccount implements Account, KeylessSigner { * @group Implementation * @category Account (On-Chain Model) */ - readonly signingScheme: SigningScheme; + readonly signingScheme: SigningScheme = SigningScheme.MultiKey; /** * The signers used to sign messages. These signers should correspond to public keys in the @@ -85,26 +87,53 @@ export class MultiKeyAccount implements Account, KeylessSigner { * @group Implementation * @category Account (On-Chain Model) */ - constructor(args: { multiKey: MultiKey; signers: Account[]; address?: AccountAddressInput }) { - const { multiKey, signers, address } = args; + constructor(args: { + multiKey: MultiKey; + signers: SingleKeySignerOrLegacyEd25519Account[]; + address?: AccountAddressInput; + }) { + const { multiKey, address } = args; + + const signers: SingleKeySigner[] = args.signers.map((signer) => + signer instanceof Ed25519Account ? SingleKeyAccount.fromEd25519Account(signer) : signer, + ); + + if (multiKey.signaturesRequired > signers.length) { + throw new Error( + // eslint-disable-next-line max-len + `Not enough signers provided to satisfy the required signatures. Need ${multiKey.signaturesRequired} signers, but only ${signers.length} provided`, + ); + } else if (multiKey.signaturesRequired < signers.length) { + throw new Error( + // eslint-disable-next-line max-len + `More signers provided than required. Need ${multiKey.signaturesRequired} signers, but ${signers.length} provided`, + ); + } this.publicKey = multiKey; - this.signingScheme = SigningScheme.MultiKey; this.accountAddress = address ? AccountAddress.from(address) : this.publicKey.authKey().derivedAddress(); - // Get the index of each respective signer in the bitmap + // For each signer, find its corresponding position in the MultiKey's public keys array const bitPositions: number[] = []; for (const signer of signers) { - bitPositions.push(this.publicKey.getIndex(signer.publicKey)); + bitPositions.push(this.publicKey.getIndex(signer.getAnyPublicKey())); } - // Zip signers and bit positions and sort signers by bit positions in order - // to ensure the signature is signed in ascending order according to the bitmap. - // Authentication on chain will fail otherwise. + + // Create pairs of [signer, position] and sort them by position + // This sorting is critical because: + // 1. The on-chain verification expects signatures to be in ascending order by bit position + // 2. The bitmap must match the order of signatures when verifying const signersAndBitPosition: [Account, number][] = signers.map((signer, index) => [signer, bitPositions[index]]); signersAndBitPosition.sort((a, b) => a[1] - b[1]); + + // Extract the sorted signers and their positions into separate arrays this.signers = signersAndBitPosition.map((value) => value[0]); this.signerIndicies = signersAndBitPosition.map((value) => value[1]); + + // Create a bitmap representing which public keys from the MultiKey are being used + // This bitmap is used during signature verification to identify which public keys + // should be used to verify each signature this.signaturesBitmap = this.publicKey.createBitmap({ bits: bitPositions }); } @@ -122,7 +151,7 @@ export class MultiKeyAccount implements Account, KeylessSigner { static fromPublicKeysAndSigners(args: { publicKeys: PublicKey[]; signaturesRequired: number; - signers: Account[]; + signers: SingleKeySignerOrLegacyEd25519Account[]; }): MultiKeyAccount { const { publicKeys, signaturesRequired, signers } = args; const multiKey = new MultiKey({ publicKeys, signaturesRequired }); diff --git a/src/account/SingleKeyAccount.ts b/src/account/SingleKeyAccount.ts index 56d13d1b3..1f17e1b80 100644 --- a/src/account/SingleKeyAccount.ts +++ b/src/account/SingleKeyAccount.ts @@ -1,10 +1,31 @@ import { AccountAuthenticatorSingleKey } from "../transactions/authenticator/account"; import { type HexInput, SigningScheme, SigningSchemeInput } from "../types"; import { AccountAddress, AccountAddressInput } from "../core/accountAddress"; -import { AnyPublicKey, AnySignature, Ed25519PrivateKey, PrivateKey, Secp256k1PrivateKey } from "../core/crypto"; +import { AnyPublicKey, AnySignature, Ed25519PrivateKey, PrivateKeyInput, Secp256k1PrivateKey } from "../core/crypto"; import type { Account } from "./Account"; import { generateSigningMessageForTransaction } from "../transactions/transactionBuilder/signingMessage"; import { AnyRawTransaction } from "../transactions/types"; +import { Ed25519Account } from "./Ed25519Account"; + +/** + * An interface which defines if an Account utilizes SingleKey signing. + * + * Such an account will use the AnyPublicKey enum to represent its public key when deriving the auth key. + */ +export interface SingleKeySigner extends Account { + getAnyPublicKey(): AnyPublicKey; +} + +export function isSingleKeySigner(obj: unknown): obj is SingleKeySigner { + return ( + typeof obj === "object" && + obj !== null && + "getAnyPublicKey" in obj && + typeof (obj as any).getAnyPublicKey === "function" + ); +} + +export type SingleKeySignerOrLegacyEd25519Account = SingleKeySigner | Ed25519Account; /** * Arguments required to create a single key signer. @@ -15,7 +36,7 @@ import { AnyRawTransaction } from "../transactions/types"; * @category Account (On-Chain Model) */ export interface SingleKeySignerConstructorArgs { - privateKey: PrivateKey; + privateKey: PrivateKeyInput; address?: AccountAddressInput; } @@ -62,13 +83,13 @@ export interface VerifySingleKeySignatureArgs { * @group Implementation * @category Account (On-Chain Model) */ -export class SingleKeyAccount implements Account { +export class SingleKeyAccount implements Account, SingleKeySigner { /** * Private key associated with the account * @group Implementation * @category Account (On-Chain Model) */ - readonly privateKey: PrivateKey; + readonly privateKey: PrivateKeyInput; readonly publicKey: AnyPublicKey; @@ -93,6 +114,10 @@ export class SingleKeyAccount implements Account { this.accountAddress = address ? AccountAddress.from(address) : this.publicKey.authKey().derivedAddress(); } + getAnyPublicKey(): AnyPublicKey { + return this.publicKey; + } + /** * Derives an account from a randomly generated private key based on the specified signing scheme. * The default generation scheme is Ed25519, but it can also support Secp256k1Ecdsa. @@ -106,7 +131,7 @@ export class SingleKeyAccount implements Account { */ static generate(args: SingleKeySignerGenerateArgs = {}) { const { scheme = SigningSchemeInput.Ed25519 } = args; - let privateKey: PrivateKey; + let privateKey: PrivateKeyInput; switch (scheme) { case SigningSchemeInput.Ed25519: privateKey = Ed25519PrivateKey.generate(); @@ -135,7 +160,7 @@ export class SingleKeyAccount implements Account { */ static fromDerivationPath(args: SingleKeySignerFromDerivationPathArgs) { const { scheme = SigningSchemeInput.Ed25519, path, mnemonic } = args; - let privateKey: PrivateKey; + let privateKey: PrivateKeyInput; switch (scheme) { case SigningSchemeInput.Ed25519: privateKey = Ed25519PrivateKey.fromDerivationPath(path, mnemonic); @@ -212,4 +237,8 @@ export class SingleKeyAccount implements Account { } // endregion + + static fromEd25519Account(account: Ed25519Account): SingleKeyAccount { + return new SingleKeyAccount({ privateKey: account.privateKey, address: account.accountAddress }); + } } diff --git a/src/account/index.ts b/src/account/index.ts index d610bfc39..2893a580f 100644 --- a/src/account/index.ts +++ b/src/account/index.ts @@ -6,3 +6,4 @@ export * from "./KeylessAccount"; export * from "./AbstractKeylessAccount"; export * from "./FederatedKeylessAccount"; export * from "./MultiKeyAccount"; +export * from "./AccountUtils"; diff --git a/src/account/utils.ts b/src/account/utils.ts new file mode 100644 index 000000000..9de9e3426 --- /dev/null +++ b/src/account/utils.ts @@ -0,0 +1,16 @@ +import { SigningScheme } from "../types"; +import { AccountAddress } from "../core"; +import { Deserializer } from "../bcs/deserializer"; + +export function deserializeSchemeAndAddress(deserializer: Deserializer): { + address: AccountAddress; + signingScheme: SigningScheme; +} { + const signingScheme = deserializer.deserializeUleb128AsU32(); + // Validate that signingScheme is a valid SigningScheme value + if (!Object.values(SigningScheme).includes(signingScheme)) { + throw new Error(`Deserialization of Account failed: SigningScheme variant ${signingScheme} is invalid`); + } + const address = AccountAddress.deserialize(deserializer); + return { address, signingScheme }; +} diff --git a/src/api/transaction.ts b/src/api/transaction.ts index d30b6516c..1fe0e2eda 100644 --- a/src/api/transaction.ts +++ b/src/api/transaction.ts @@ -36,7 +36,7 @@ import { InputGenerateTransactionOptions, InputGenerateTransactionPayloadData, } from "../transactions"; -import { AccountAddressInput, PrivateKey } from "../core"; +import { AccountAddressInput, PrivateKeyInput } from "../core"; import { Account } from "../account"; import { Build } from "./transactionSubmission/build"; import { Simulate } from "./transactionSubmission/simulate"; @@ -506,7 +506,7 @@ export class Transaction { * ``` * @group Transaction */ - async rotateAuthKey(args: { fromAccount: Account; toNewPrivateKey: PrivateKey }): Promise { + async rotateAuthKey(args: { fromAccount: Account; toNewPrivateKey: PrivateKeyInput }): Promise { return rotateAuthKey({ aptosConfig: this.config, ...args }); } diff --git a/src/bcs/deserializer.ts b/src/bcs/deserializer.ts index f9d05ff47..fc6748499 100644 --- a/src/bcs/deserializer.ts +++ b/src/bcs/deserializer.ts @@ -3,7 +3,8 @@ /* eslint-disable no-bitwise */ import { MAX_U32_NUMBER } from "./consts"; -import { Uint8, Uint16, Uint32, Uint64, Uint128, Uint256 } from "../types"; +import { Uint8, Uint16, Uint32, Uint64, Uint128, Uint256, HexInput } from "../types"; +import { Hex } from "../core/hex"; /** * This interface exists to define Deserializable inputs for functions that @@ -62,6 +63,11 @@ export class Deserializer { this.offset = 0; } + static fromHex(hex: HexInput): Deserializer { + const data = Hex.hexInputToUint8Array(hex); + return new Deserializer(data); + } + /** * Reads a specified number of bytes from the buffer and advances the offset. * diff --git a/src/core/crypto/multiKey.ts b/src/core/crypto/multiKey.ts index 9406da532..6414e89e4 100644 --- a/src/core/crypto/multiKey.ts +++ b/src/core/crypto/multiKey.ts @@ -218,7 +218,7 @@ export class MultiKey extends AccountPublicKey { if (index !== -1) { return index; } - throw new Error("Public key not found in MultiKey"); + throw new Error(`Public key ${publicKey} not found in MultiKey ${this.publicKeys}`); } public static isInstance(value: PublicKey): value is MultiKey { diff --git a/src/core/crypto/singleKey.ts b/src/core/crypto/singleKey.ts index cfc6cf651..8ee12c2ff 100644 --- a/src/core/crypto/singleKey.ts +++ b/src/core/crypto/singleKey.ts @@ -1,13 +1,15 @@ import { Deserializer, Serializer } from "../../bcs"; import { AnyPublicKeyVariant, AnySignatureVariant, SigningScheme as AuthenticationKeyScheme } from "../../types"; import { AuthenticationKey } from "../authenticationKey"; -import { Ed25519PublicKey, Ed25519Signature } from "./ed25519"; +import { Ed25519PrivateKey, Ed25519PublicKey, Ed25519Signature } from "./ed25519"; import { AccountPublicKey, PublicKey, VerifySignatureArgs } from "./publicKey"; -import { Secp256k1PublicKey, Secp256k1Signature } from "./secp256k1"; +import { Secp256k1PrivateKey, Secp256k1PublicKey, Secp256k1Signature } from "./secp256k1"; import { KeylessPublicKey, KeylessSignature } from "./keyless"; import { Signature } from "./signature"; import { FederatedKeylessPublicKey } from "./federatedKeyless"; +export type PrivateKeyInput = Ed25519PrivateKey | Secp256k1PrivateKey; + /** * Represents any public key supported by Aptos. * diff --git a/src/internal/transactionSubmission.ts b/src/internal/transactionSubmission.ts index 16def0e5a..fd80e0307 100644 --- a/src/internal/transactionSubmission.ts +++ b/src/internal/transactionSubmission.ts @@ -11,7 +11,7 @@ import { Deserializer, MoveVector, U8 } from "../bcs"; import { postAptosFullNode } from "../client"; import { Account, AbstractKeylessAccount, isKeylessSigner } from "../account"; import { AccountAddress, AccountAddressInput } from "../core/accountAddress"; -import { FederatedKeylessPublicKey, KeylessPublicKey, KeylessSignature, PrivateKey } from "../core/crypto"; +import { FederatedKeylessPublicKey, KeylessPublicKey, KeylessSignature, PrivateKeyInput } from "../core/crypto"; import { AccountAuthenticator } from "../transactions/authenticator/account"; import { RotationProofChallenge } from "../transactions/instances/rotationProofChallenge"; import { @@ -474,7 +474,7 @@ const rotateAuthKeyAbi: EntryFunctionABI = { export async function rotateAuthKey(args: { aptosConfig: AptosConfig; fromAccount: Account; - toNewPrivateKey: PrivateKey; + toNewPrivateKey: PrivateKeyInput; }): Promise { const { aptosConfig, fromAccount, toNewPrivateKey } = args; const accountInfo = await getInfo({ diff --git a/tests/e2e/transaction/transactionSubmission.test.ts b/tests/e2e/transaction/transactionSubmission.test.ts index d9536c9ed..d6f05b18d 100644 --- a/tests/e2e/transaction/transactionSubmission.test.ts +++ b/tests/e2e/transaction/transactionSubmission.test.ts @@ -662,6 +662,17 @@ describe("transaction submission", () => { }); expect(response.signature?.type).toBe("single_sender"); }); + test("constructing a multi key account with insufficient signers fails", async () => { + const multiKey = new MultiKey({ + publicKeys: [ + singleSignerED25519SenderAccount.publicKey, + legacyED25519SenderAccount.publicKey, + singleSignerSecp256k1Account.publicKey, + ], + signaturesRequired: 2, + }); + expect(() => new MultiKeyAccount({ multiKey, signers: [singleSignerED25519SenderAccount] })).toThrow(); + }); }); describe("publish move module", () => { const account = Account.generate(); diff --git a/tests/unit/accountSerialization.test.ts b/tests/unit/accountSerialization.test.ts new file mode 100644 index 000000000..dcfc4a0e1 --- /dev/null +++ b/tests/unit/accountSerialization.test.ts @@ -0,0 +1,120 @@ +/* eslint-disable max-len */ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +import { + Account, + SigningSchemeInput, + MultiKeyAccount, + KeylessAccount, + FederatedKeylessAccount, + EphemeralKeyPair, + ZeroKnowledgeSig, + ZkProof, + Groth16Zkp, + ZkpVariant, + Groth16VerificationKey, +} from "../../src"; +import { AccountUtils } from "../../src/account/AccountUtils"; + +export function testAccountSerializationDeserialization(account: Account) { + const bytes = AccountUtils.toBytes(account); + const deserializedAccount = AccountUtils.fromBytes(bytes); + expect(bytes).toEqual(AccountUtils.toBytes(deserializedAccount)); +} + +describe("Account Serialization", () => { + const proof = new ZeroKnowledgeSig({ + proof: new ZkProof( + new Groth16Zkp({ a: new Uint8Array(32), b: new Uint8Array(64), c: new Uint8Array(32) }), + ZkpVariant.Groth16, + ), + expHorizonSecs: 0, + }); + const verificationKey = new Groth16VerificationKey({ + alphaG1: new Uint8Array(32), + betaG2: new Uint8Array(64), + deltaG2: new Uint8Array(64), + gammaAbcG1: [new Uint8Array(32), new Uint8Array(32)], + gammaG2: new Uint8Array(64), + }); + const jwt = + "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJ0ZXN0IiwiYXVkIjoidGVzdC1hdWQiLCJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNzMxMjE0NTIxLCJleHAiOjE3MzEyMTgxMjF9.jZeCpYDDWx0pW_WcBpg8b0NzDWCABvH3lSmmmub8BBg"; + + const legacyEdAccount = Account.generate(); + const singleSignerEdAccount = Account.generate({ scheme: SigningSchemeInput.Ed25519, legacy: false }); + const secp256k1Account = Account.generate({ scheme: SigningSchemeInput.Secp256k1Ecdsa }); + const keylessAccount = KeylessAccount.create({ + proof, + ephemeralKeyPair: EphemeralKeyPair.generate(), + pepper: new Uint8Array(31), + jwt, + }); + const keylessAccountWithVerificationKey = KeylessAccount.create({ + proof, + ephemeralKeyPair: EphemeralKeyPair.generate(), + pepper: new Uint8Array(31), + jwt, + verificationKey, + }); + const federatedKeylessAccount = FederatedKeylessAccount.create({ + ephemeralKeyPair: EphemeralKeyPair.generate(), + pepper: new Uint8Array(31), + jwt, + jwkAddress: Account.generate().accountAddress, + proof, + }); + const multiKeyAccount = MultiKeyAccount.fromPublicKeysAndSigners({ + publicKeys: [singleSignerEdAccount.publicKey, secp256k1Account.publicKey, Account.generate().publicKey], + signaturesRequired: 2, + signers: [singleSignerEdAccount, secp256k1Account], + }); + const keylessAccountWithBackupSigner = MultiKeyAccount.fromPublicKeysAndSigners({ + publicKeys: [keylessAccount.publicKey, Account.generate().publicKey], + signaturesRequired: 1, + signers: [keylessAccount], + }); + + describe("serialize", () => { + it("legacy Ed25519 Account should serlialize and deserialize properly", () => { + testAccountSerializationDeserialization(legacyEdAccount); + const accountAsHex = AccountUtils.toHexString(legacyEdAccount); + expect(legacyEdAccount).toEqual(AccountUtils.ed25519AccountFromHex(accountAsHex)); + }); + it("SingleKey Ed25519 Account should serlialize and deserialize properly", () => { + testAccountSerializationDeserialization(singleSignerEdAccount); + const accountAsHex = AccountUtils.toHexString(singleSignerEdAccount); + expect(singleSignerEdAccount).toEqual(AccountUtils.singleKeyAccountFromHex(accountAsHex)); + }); + it("SingleKey Secp256k1 Account should serlialize and deserialize properly", () => { + testAccountSerializationDeserialization(secp256k1Account); + const accountAsHex = AccountUtils.toHexString(secp256k1Account); + expect(secp256k1Account).toEqual(AccountUtils.singleKeyAccountFromHex(accountAsHex)); + }); + it("Keyless Account should serlialize and deserialize properly", () => { + testAccountSerializationDeserialization(keylessAccount); + const accountAsHex = AccountUtils.toHexString(keylessAccount); + expect(keylessAccount).toEqual(AccountUtils.keylessAccountFromHex(accountAsHex)); + }); + it("Keyless Account with verification key should serlialize and deserialize properly", () => { + testAccountSerializationDeserialization(keylessAccountWithVerificationKey); + const accountAsHex = AccountUtils.toHexString(keylessAccountWithVerificationKey); + expect(keylessAccountWithVerificationKey).toEqual(AccountUtils.keylessAccountFromHex(accountAsHex)); + }); + it("FederatedKeyless Account should serlialize and deserialize properly", () => { + testAccountSerializationDeserialization(federatedKeylessAccount); + const accountAsHex = AccountUtils.toHexString(federatedKeylessAccount); + expect(federatedKeylessAccount).toEqual(AccountUtils.federatedKeylessAccountFromHex(accountAsHex)); + }); + it("MultiKey Account should serlialize and deserialize properly", () => { + testAccountSerializationDeserialization(multiKeyAccount); + const accountAsHex = AccountUtils.toHexString(multiKeyAccount); + expect(multiKeyAccount).toEqual(AccountUtils.multiKeyAccountFromHex(accountAsHex)); + }); + it("MultiKey Account with backup signer should serlialize and deserialize properly", () => { + testAccountSerializationDeserialization(keylessAccountWithBackupSigner); + const accountAsHex = AccountUtils.toHexString(keylessAccountWithBackupSigner); + expect(keylessAccountWithBackupSigner).toEqual(AccountUtils.multiKeyAccountFromHex(accountAsHex)); + }); + }); +});