Commit 039f2fa
Feature/marketplace checkout (#251)
* Implement GenerateBuyTransaction endpoint/request support
* Added sardine whitelist checking support
* Integrate GetSardineSupportedRegions request
* Added GetSardineClientToken endpoint support
* Basic integration for sardine checkout. Moved CollectibleOrder and dependant classes to the Integrations assembly so that Marketplace assembly can inherrit from Integrations assembly (using Transak and Sardine)
* Checkout Options implementation
* Implemented support for the remaining marketplace reader API requests
* GetCheckoutOptions using Order[]
* Added events for reading callbacks and updated tests to make sure they are being hit
* Add tests for checking the supported checkout options for a given order array
* Generate buy transaction implementation and test
* Fixed ListCurrencies implementation such that tests pass
* Finish generateBuyTransaction interface and finish writing test
* Fix GetCollectible implementation such that tests pass
* Rename get collectible listing/offer requests and tests
* Rename ListCollectibleListings/Offers to ListListings/Offers-ForCollectibles and add missing tests
* Rename ListCollectiblesWithLowestListing/HighestOffer to more descriptive names and fix implementation to new endpoint configuration and update test namings
* Remove TransactionGenerator as it was unused and duplicating code
* Added GenerateSellTransaction method and test
* Fix json construction
* Fix GenerateBuy/Sell-Transaction calls such that buy tests pass
* Added GenerateListingTransaction and GenerateOfferTransaction implementation and tests
* Refactor such that I use a more generic EnumConverter as opposed to creating separate json converters for each enum
* Fixed GetCheckoutOptions implementation and test
* Added GetFloorOrder implementation
* Updated Transak NFT checkout integration - not currently working, I am told I have invalid calldata when opening the link. I am also needing to mock the gas estimation as my estimator thinks the transaction will revert (which makes sense as I wouldn't be executing)
* Added Sardine data types
* Added SardineGetNFTCheckoutToken integration and test. Cleaner testing interface
* Handle gas currency case by checking for currency address = zero address
* FirstCommitForQr (#170)
* FirstCommitForQr
Qr Setup and exposure with link to add funds for the respective order chain id in native token address
* More automatization on adding funds
Detecting specifics straight from collectible order
* Automated inputs for QR
Included automated inputs for adding funds via qr transfer link. Fills Qr with selected order Order component information.
* Updated qr token address setting
Made check for nativetokenaddress placeholder to use in case ChainTokenAddress.Get(),(renamed) and also made some minor ui text updates.
* Standarized to EIP-618 transfer link
It includes all etheremum eip-618 compatible wallets (metamask is such). Also revisions on price names and formats
* Use dev for now
* Add preserve compiler tag to constructors that are used by Newtonsoft for json serialization/deserialization so that they don't get striped during builds
* Fix broken tests
* Rename orderbookKind arg to orderbook
* Fixed SardineGetSupportedRegions request and httpclient
* Fix broken test
* Fix more tests
* Fix more tests
* Reset session id and session wallet when trying to login not when logged out. Additionally, removed the federate auth methods from the GuestConnector since this flow isn't supported
* Fix broken tests
* Added basic swap api integration and tests
* Use polygon for test
* Update currency swap API, the slippage percentage is in percentage not in basis points. GetSwapQuote will now first confirm the user has sufficient funds before swapping; unfulfilled swap quotes lead to Sequence being penalized. Fix broken tests
* Throw an exception if we get a null response from API without an error attached
* Fix broken tests and add additional tests for the pre validation before sending swap quote request
* Fix broken generate listing transaction test implementation
* add CreateListingAndBuyIt end to end test
* Finish CreateListingAndBuyIt end to end test
* fixed stuck in loading screen when a user entered an empty email
* Added retry logic to CreateListingAndBuyIt test as the orders are not always refreshed right away which was causing the test to be spotty. The test was still spotty so I added a SeedMarketplace method that can be run to seed the marketplace with 100 offers and 100 listings, this uses a fair amount of credits to run so it should be done sparingly. Added a CreateOfferAndSellIt method that tests the other side of the marketplace. Switched to prod. Fixed GenerateSellTransaction implementation
* Fix GenerateBuy/SellTransaction interface to include amount to buy/sell
* Fix broken tests. Move marketplace seeding logic to its own class MarketplaceSeeder
* Switch currency swap to prod api
* Fix test implementation
* Rename SeeMarketplaceListingsPage/Panel to ViewMarketplaceListingsPage/Panel so we don't look like we've made typos when having an Open... method.
* Added GenerateCancelRequest support and test. Test cleanup
* Added default contract to viewMarketplaceListingsPage
* Update cancel order test such that I filter my fetch to only include the orders created by my wallet
* Added ListAllSellableOffers and ListAllPurchasableListings methods to reader and unit tests
* Added IReader interface with intellisence summaries that is implemented by MarketplaceReader. Added some additional unit tests
* Added ICheckout interface with intellisence summaries that is implemented by Checkout. Added callback events to Checkout. Added intellisence summaries to FilterAffordableOrders
* Extended Step[] such that it is easier to turn these into transactions and submit
* Added ISwap interface with intellisence summary implemented by CurrencySwap. Added callback events
* Update ViewMarketplacePage such that listings are shown with their prices listed in cryptocurrency (with the associated currency token icon displayed) and available amount
* Fetch mock collectible orders for now. Add focus button for marketplace tiles and buy button. Also setup support for token info page
* Populate checkout page with CartItems
* Fix transition screen UI
* increment package version
* Fix broken test
* Switch to prod
* Added Cart and respective tests
* Create a cart with a single listing. Return a decorated error message if we fail to fetch a swap price
* Fix listings page assembly. Add mising array utils function
* Revert "Switch to prod"
This reverts commit 1582e50.
* Update intellisense summaries and fix broken tests
* Build temporary scene to make it easier to update checkout page UI. Add working scrollview to CheckoutPage
* Instantiate estimated cost area, network banner, and divider
* Instantiate crypto payment options
* Checkout setup. Additional CartTests
* increment package version
* Migrate CheckoutPage to use an ICheckoutHelper interface, implemented by Cart and NftCheckout (the same as Cart but with a max of one collectible in the cart). New dev endpoint.
* Get checkout UI working with mocks
* Purchase tokens via demo scene
* Incrementing or decrementing amount of tokens refreshes UI
* Fix broken test
* Fix decimal normalizer for large BigInts
* Add test for purchasing listing with native currency
* Fund account with QR code
* Clear spawned items in CheckoutPage when we close so that we don't end up spawning extra stuff on subsequent openings
* Added on-ramp button to checkout page, supporting transak
* include placeholder image url and name for sardine as these are required
* Added intellisense summaries for ICheckoutHelper
* Switch tests to using dev env
* Rename IReader to IMarketplaceReader
* Rename mock
* Fix compile error
* Cleanup CheckoutPage implementation and make most methods protected to make the class easier to extend
* Fix transak nft checkout test
* Cleanup - remove code I'm not as confident in and remove Temp scene + scripts
* Added properties to TokenMetadata
* Fix decimal precision issues when converting back into normal human readable decimal format from EVM number format
* Switch to new easy mint token
* Don't use dev environment for tests anymore
* Revert "Cleanup - remove code I'm not as confident in and remove Temp scene + scripts"
This reverts commit 2393d35.
* Remove temp folder
* Add implementation for missing Sardine endpoints and miscellaneous fixes to Sardine implementation
* Use prod for Tranak test
* Fix generate offer transaction test - it seems like the API now checks that you have sufficient balance and will error if not - added an assertion to the test to confirm we have sufficient balance so we don't have false fails and pre-seeded the test wallet with lots of easy mint erc20 so our test passes again as expected.
* Created ContractWrapper class that Ownable (and derived classes) derive from - it is intended that contract wrappers should inherit from it. Added an implicit operator to Contract and ContractWrapper such that you can use either of them as an Address directly (instead of using getters to get the associated Address)
* chore: foundry install
* forge install: forge-std
v1.9.5
* Foundry setup
* Added basic erc1155 sales test
* Foundry usage instructions
* Fix erc1155/721 sale contracts
* Working Sardine primary sales integration. Additional sardine endpoints and tests. Don't allow offers with native currencies.
* Additional GetCheckoutOptions methods for primary sales contracts. Filter Sardine tokens responses based on network. Test refactoring.
* Fix Transak calldata compression utility
* Added ISardineCheckout interface (implemented by SardineCheckout) with intellisense summaries. Added some pre-emptive error handling for SardineCheckout - throwing exceptions for operations now supported by Sardine like using native tokens
* Successful transak checkout link generation
* Cleaner transak implementation
* Move calldata and nft data compression/encoding logic to standalone static classes and add tests to confirm they work (using examples from kit)
* Fixed transak test and implementation for PrimarySaleERC1155 contract wrapper such that we use fixed bytes instead as this is less error prone
* Use decimal instead of float or double for prices in USD so we avoid accuracy issues
* Mint a large number of tokens for this test - was useful to verify that we don't lose accuracy when sending large numbers via API for an integrator - might as well stay as a modification to the test to confirm this remains the case
* Remove commented out code that is no longer needed
* Integrated the SardineGetQuote API
* Optionally provide a different buy address when generating buy transaction via API
* Don't require TransakContractId when checking out with a CollectibleOrder - this can be retrieved as any MarketplaceKind that isn't one of the sequence marketplace versions is reservoir OrderbookKind
* Rename Integrations namespace to Pay and accordingly renamed SequenceIntegrations asmdef to SequencePay
* Added IFiatPay interface implemented by SequencePay (the main class for fiat checkout) and updated MarketplaceCheckout interfaces such that they support buying/selling multiple orders for the same item
* Added ERG using mermaid
* Added IFiatCheckout and hooked it up with the CheckoutPanel/page/modal
* Modify class diagram
* Added Sequence marketplace v2 contract on Polygon to Transak whitelist
* Added append array generic helper
* Added GetHashCode override for Address class so that we can use it in Dictionaries as a key and not encounter issues with value comparison
* Throw an error if we get a null swap price from API
* Initialize TransakFiatPay instance
* Fix error message
* Cache config objects in a dictionary so we can load multiple configs at once and target different envs for different services successfully
* Fix checkout UI such that it uses ICheckoutHelper and IFiatCheckout and modified ICheckoutHelper such that it is based on collectibles instead of order ids for additional flexibility and to support primary sales as well
* Fix broken checkout and reader tests
* Fix broken test
* Checkout modal now reacts when incrementing or decrementing amount requesting when generating nft checkout links using Transak or Sardine
* Make sardine checkout code more readable
* Use CartItemData DTO instead of using CollectibleOrders when assembling our CartItems; this will make it so that CartItems can be re-used with primary sales contracts
* Added price feeds
* Fix sardine checkout
* Add ERC1155SaleCheckout implementation - this should enable us to use the CheckoutPanel in conjunction with primary sales
* Remove GetCollectiblePrices as this endpoint doesn't seem to be working
* Fix crypto checkout for primary sales. Add Checkout modal demo
* Added sequence diagrams
* Fix sequence diagram
* Fix typo/compile error
* Added basic unit tests for NftCheckout class - we'll want to add end-to-end tests later on. Fixed a null reference exception in NftCheckout due to having uninitialized values (that need fetching from APIs)
* Remove Cart and tests because I am not confident with how they fit into the rest of the package
* Fix typo
* Metadata has been updated and .png now exists
* Remove redundant line
* Fix build error by including ionic zip dll
* Listing and offer UI (#261)
* ListItem, SellOffer, CreateOffer UI
* Reverted CheckoutPanel.prefab from commit c78cdf0
* Move order orchestration logic (requesting additional orders and allocating amounts to them until we can fulfill user's request) into its own class 'OrderOrchestrator' and use it as a dependency for both NftCheckout and SequenceCheckout. This fixes a bug where SequenceCheckout wouldn't request additional orders as the amount requested grew beyond the present order's availability
* Move order orchestration logic (requesting additional orders and allocating amounts to them until we can fulfill user's request) into its own class 'OrderOrchestrator' and use it as a dependency for both NftCheckout and SequenceCheckout. This fixes a bug where SequenceCheckout wouldn't request additional orders as the amount requested grew beyond the present order's availability (#268)
* Fix/optimize checkout page load (#269)
* Move order orchestration logic (requesting additional orders and allocating amounts to them until we can fulfill user's request) into its own class 'OrderOrchestrator' and use it as a dependency for both NftCheckout and SequenceCheckout. This fixes a bug where SequenceCheckout wouldn't request additional orders as the amount requested grew beyond the present order's availability
* Optimize CheckoutPage load by making less API requests (re-ordering the way they are done)
* Fix GenericObjectPool such that it grows in size as needed
* Fix demo scene
* Fix test data to reflect new metadata and fix DecimalNormalizer so that it drops trailing 0s after the decimal point '.' in numbers (failure to do so can cause encoding issues)
* Fix scroll view
* Ignore case when comparing addresses
* Remove temp folder with unneeded code
* Replace demo scene with working version
* Move Boilerplate scripts back into the SequenceFrontend assembly. This maintains existing functionality and allows us to ship updates to the SDK code just like the rest of the package. Otherwise, devs will need to import it via samples in order to use them and will miss out on any fixes we push out unless they re-import the samples (which would give them everything again). This makes the Boilerplate code immutable, but it makes it more effective as sample code and easier to get updated.
* Fix PlayMode tests and mark UI tests to be ignored as they haven't been working for some time and aren't relevant with our new Boilerplate based UI system. I've left the UI tests in for now as a reference in case we ever do revisit them; if we do, we'll want to be careful about how many we write as the test suite can take a long time to run and can be difficult to effectively parallelize.
* Fix mermaid diagram
* Catch and log errors when generating checkout link in CheckoutPage
* Added ADR to explain marketplace + pay architecture. Additionally, ad… (#272)
* Added ADR to explain marketplace + pay architecture. Additionally, added a github action to embed the mermaid diagram in the Readme
* Embed the mermaid diagram directly into the ADR since it is timestamped
* Fix tests by pointing at a different collection
* Update to new boilerplates (#271)
* Merge updateToNewBoilerplates branch into Feature/marketplaceCheckout
* Fix date picker drodown options
---------
Co-authored-by: Quinn Purdy <[email protected]>
* Move sprites out of samples and into SDK
* Re-add sprites to prefab
---------
Co-authored-by: Tomas Kolakovic <[email protected]>
Co-authored-by: Andy Grüning <[email protected]>1 parent 421ec96 commit 039f2fa
File tree
674 files changed
+39929
-2064
lines changed- Assets
- GuestLogin
- PlayFab/PlayFabEditorExtensions/Editor/Resources
- SequenceFrontend
- Scenes
- Tests
- SequenceSDK
- Ethereum/Tests
- Indexer/Tests
- Marketplace
- Mocks
- Pay
- Tests
- Mocks
- Sardine
- Transak
- Relayer/Tests
- WaaS/Tests
- Packages/Sequence-Unity
- Plugins
- Android
- Sequence
- Samples~
- DemoScene
- Setup
- Boilerplates
- Resources/Prefabs
- Checkout
- Common
- InGameShop
- Inventory
- Marketplace
- Scripts/Common
- Resources
- SequenceFrontend
- Prefabs
- Scripts
- Tweening
- UI
- Boilerplates
- Common
- DailyRewards
- InGameShop
- Inventory
- Login
- Marketplace
- PlayerProfile
- SignMessage
- Demos
- PrimarySales
- Helpers
- Marketplace
- Mocks
- QrCode
- Sprites
- Boilerplates
- Icons
- SequenceSDK
- Config
- EmbeddedWallet
- Ethereum
- ABI
- Coders
- Contract
- Provider
- Transaction
- Indexer
- DataTypes
- Integrations
- Marketplace
- DataTypes
- Pay
- Sardine
- DataTypes
- Transak
- DataTypes
- Utils
- ProjectSettings
- testchain
- contracts
- lib
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
674 files changed
+39929
-2064
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
118 | 118 | | |
119 | 119 | | |
120 | 120 | | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
| 13 | + | |
| 14 | + | |
13 | 15 | | |
14 | 16 | | |
15 | 17 | | |
| |||
25 | 27 | | |
26 | 28 | | |
27 | 29 | | |
28 | | - | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
29 | 34 | | |
30 | 35 | | |
31 | 36 | | |
| |||
58 | 63 | | |
59 | 64 | | |
60 | 65 | | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
61 | 71 | | |
62 | 72 | | |
Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
38 | 38 | | |
39 | 39 | | |
40 | 40 | | |
41 | | - | |
| 41 | + | |
42 | 42 | | |
43 | 43 | | |
44 | 44 | | |
| |||
576 | 576 | | |
577 | 577 | | |
578 | 578 | | |
| 579 | + | |
| 580 | + | |
| 581 | + | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
| 590 | + | |
| 591 | + | |
| 592 | + | |
| 593 | + | |
| 594 | + | |
| 595 | + | |
| 596 | + | |
| 597 | + | |
| 598 | + | |
| 599 | + | |
| 600 | + | |
| 601 | + | |
| 602 | + | |
| 603 | + | |
| 604 | + | |
| 605 | + | |
| 606 | + | |
| 607 | + | |
| 608 | + | |
| 609 | + | |
| 610 | + | |
| 611 | + | |
| 612 | + | |
| 613 | + | |
| 614 | + | |
| 615 | + | |
| 616 | + | |
| 617 | + | |
| 618 | + | |
| 619 | + | |
| 620 | + | |
| 621 | + | |
| 622 | + | |
| 623 | + | |
| 624 | + | |
| 625 | + | |
| 626 | + | |
| 627 | + | |
| 628 | + | |
| 629 | + | |
| 630 | + | |
| 631 | + | |
| 632 | + | |
| 633 | + | |
| 634 | + | |
| 635 | + | |
| 636 | + | |
| 637 | + | |
| 638 | + | |
| 639 | + | |
| 640 | + | |
| 641 | + | |
| 642 | + | |
| 643 | + | |
| 644 | + | |
| 645 | + | |
| 646 | + | |
| 647 | + | |
| 648 | + | |
| 649 | + | |
| 650 | + | |
| 651 | + | |
| 652 | + | |
| 653 | + | |
| 654 | + | |
| 655 | + | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
| 667 | + | |
| 668 | + | |
| 669 | + | |
| 670 | + | |
| 671 | + | |
| 672 | + | |
| 673 | + | |
| 674 | + | |
| 675 | + | |
| 676 | + | |
| 677 | + | |
| 678 | + | |
| 679 | + | |
| 680 | + | |
| 681 | + | |
| 682 | + | |
| 683 | + | |
| 684 | + | |
| 685 | + | |
| 686 | + | |
| 687 | + | |
| 688 | + | |
| 689 | + | |
| 690 | + | |
| 691 | + | |
| 692 | + | |
| 693 | + | |
| 694 | + | |
| 695 | + | |
| 696 | + | |
| 697 | + | |
| 698 | + | |
| 699 | + | |
| 700 | + | |
| 701 | + | |
| 702 | + | |
| 703 | + | |
| 704 | + | |
| 705 | + | |
| 706 | + | |
| 707 | + | |
| 708 | + | |
| 709 | + | |
| 710 | + | |
| 711 | + | |
| 712 | + | |
| 713 | + | |
579 | 714 | | |
580 | 715 | | |
581 | 716 | | |
| |||
781 | 916 | | |
782 | 917 | | |
783 | 918 | | |
| 919 | + | |
| 920 | + | |
| 921 | + | |
| 922 | + | |
| 923 | + | |
| 924 | + | |
| 925 | + | |
| 926 | + | |
| 927 | + | |
| 928 | + | |
| 929 | + | |
| 930 | + | |
| 931 | + | |
| 932 | + | |
| 933 | + | |
| 934 | + | |
| 935 | + | |
| 936 | + | |
| 937 | + | |
| 938 | + | |
| 939 | + | |
| 940 | + | |
| 941 | + | |
| 942 | + | |
| 943 | + | |
| 944 | + | |
| 945 | + | |
| 946 | + | |
| 947 | + | |
| 948 | + | |
| 949 | + | |
| 950 | + | |
| 951 | + | |
| 952 | + | |
| 953 | + | |
| 954 | + | |
| 955 | + | |
| 956 | + | |
| 957 | + | |
| 958 | + | |
| 959 | + | |
| 960 | + | |
| 961 | + | |
| 962 | + | |
| 963 | + | |
| 964 | + | |
| 965 | + | |
| 966 | + | |
| 967 | + | |
| 968 | + | |
| 969 | + | |
| 970 | + | |
| 971 | + | |
| 972 | + | |
| 973 | + | |
| 974 | + | |
| 975 | + | |
| 976 | + | |
| 977 | + | |
| 978 | + | |
| 979 | + | |
| 980 | + | |
| 981 | + | |
| 982 | + | |
| 983 | + | |
| 984 | + | |
| 985 | + | |
| 986 | + | |
| 987 | + | |
| 988 | + | |
| 989 | + | |
| 990 | + | |
| 991 | + | |
| 992 | + | |
| 993 | + | |
| 994 | + | |
| 995 | + | |
| 996 | + | |
| 997 | + | |
| 998 | + | |
| 999 | + | |
| 1000 | + | |
| 1001 | + | |
| 1002 | + | |
| 1003 | + | |
| 1004 | + | |
| 1005 | + | |
| 1006 | + | |
| 1007 | + | |
| 1008 | + | |
| 1009 | + | |
| 1010 | + | |
| 1011 | + | |
| 1012 | + | |
| 1013 | + | |
| 1014 | + | |
| 1015 | + | |
| 1016 | + | |
| 1017 | + | |
| 1018 | + | |
| 1019 | + | |
| 1020 | + | |
| 1021 | + | |
| 1022 | + | |
| 1023 | + | |
| 1024 | + | |
| 1025 | + | |
| 1026 | + | |
| 1027 | + | |
| 1028 | + | |
| 1029 | + | |
| 1030 | + | |
| 1031 | + | |
| 1032 | + | |
| 1033 | + | |
| 1034 | + | |
| 1035 | + | |
| 1036 | + | |
| 1037 | + | |
| 1038 | + | |
| 1039 | + | |
| 1040 | + | |
| 1041 | + | |
| 1042 | + | |
| 1043 | + | |
| 1044 | + | |
| 1045 | + | |
| 1046 | + | |
| 1047 | + | |
| 1048 | + | |
| 1049 | + | |
| 1050 | + | |
| 1051 | + | |
| 1052 | + | |
| 1053 | + | |
| 1054 | + | |
| 1055 | + | |
| 1056 | + | |
| 1057 | + | |
| 1058 | + | |
| 1059 | + | |
| 1060 | + | |
| 1061 | + | |
| 1062 | + | |
| 1063 | + | |
| 1064 | + | |
| 1065 | + | |
| 1066 | + | |
784 | 1067 | | |
785 | 1068 | | |
786 | 1069 | | |
| |||
1211 | 1494 | | |
1212 | 1495 | | |
1213 | 1496 | | |
| 1497 | + | |
| 1498 | + | |
| 1499 | + | |
| 1500 | + | |
| 1501 | + | |
1214 | 1502 | | |
1215 | 1503 | | |
1216 | 1504 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
| 4 | + | |
4 | 5 | | |
5 | 6 | | |
6 | 7 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
| 3 | + | |
3 | 4 | | |
4 | 5 | | |
5 | 6 | | |
| |||
0 commit comments