@@ -39,7 +39,7 @@ module ob_kiosk::ob_kiosk {
3939 use sui::dynamic_field::{Self as df};
4040 use sui::kiosk::{Self , Kiosk , KioskOwnerCap , uid, uid_mut as ext};
4141 use sui::object::{Self , ID , UID , uid_to_address};
42- use sui::coin;
42+ use sui::coin::{ Self , Coin } ;
4343 use sui::table::{Self , Table };
4444 use sui::transfer::{transfer, public_share_object, public_transfer};
4545 use sui::tx_context::{Self , TxContext , sender};
@@ -55,6 +55,7 @@ module ob_kiosk::ob_kiosk {
5555 // Track the current version of the module
5656 const VERSION : u64 = 3 ;
5757
58+ const EDeprecatedApi : u64 = 998 ;
5859 const ENotUpgraded : u64 = 999 ;
5960 const EWrongVersion : u64 = 1000 ;
6061
@@ -328,8 +329,11 @@ module ob_kiosk::ob_kiosk {
328329 assert_version_and_upgrade (ext (self));
329330 assert_can_deposit <T >(self, ctx);
330331
332+ let nft_id = object::id (&nft);
333+
331334 let cap = pop_cap (self);
332- deposit_ (self, &cap, nft);
335+ kiosk::place (self, &cap, nft);
336+ register_nft_ (self, nft_id);
333337 set_cap (self, cap);
334338 }
335339
@@ -353,29 +357,41 @@ module ob_kiosk::ob_kiosk {
353357 let cap = pop_cap (self);
354358 while (!vector ::is_empty (&nfts)) {
355359 let nft = vector ::pop_back (&mut nfts);
356- deposit_ (self, &cap, nft);
360+ let nft_id = object::id (&nft);
361+ kiosk::place (self, &cap, nft);
362+ register_nft_ (self, nft_id);
357363 };
358364
359365 vector ::destroy_empty (nfts);
360366 set_cap (self, cap);
361367 }
362368
363- /// Deposits NFT into `Kiosk` and handles `NftRef` accounting
364- fun deposit_ <T : key + store >(
369+ /// Deposit an NFT and lock it within the `Kiosk`
370+ ///
371+ /// NFTs deposited using `deposit_locked` must use `transfer_locked_nft` to
372+ /// transfer the NFT.
373+ ///
374+ /// Useful for interacting with non-OB collections.
375+ ///
376+ /// #### Panics
377+ ///
378+ /// Panics if transaction sender is not owner or `Kiosk` is not
379+ /// permissionless.
380+ public fun deposit_locked <T : key + store >(
365381 self: &mut Kiosk ,
366- cap : &KioskOwnerCap ,
382+ policy : &sui:: transfer_policy :: TransferPolicy < T > ,
367383 nft: T ,
384+ ctx: &mut TxContext ,
368385 ) {
369- let nft_id = object::id (&nft);
386+ assert_version_and_upgrade (ext (self));
387+ assert_can_deposit <T >(self, ctx);
370388
371- let refs = nft_refs_mut (self);
372- table::add (refs, nft_id, NftRef {
373- auths: vec_set::empty (),
374- is_exclusively_listed: false ,
375- });
389+ let nft_id = object::id (&nft);
376390
377- // place underlying NFT to kiosk
378- kiosk::place (self, cap, nft);
391+ let cap = pop_cap (self);
392+ kiosk::lock (self, &cap, policy, nft);
393+ register_nft_ (self, nft_id);
394+ set_cap (self, cap);
379395 }
380396
381397 // === Withdraw from the Kiosk ===
@@ -522,6 +538,8 @@ module ob_kiosk::ob_kiosk {
522538
523539 /// Transfer NFT out of Kiosk that has been previously delegated
524540 ///
541+ /// NFT will not be locked in the target `Kiosk`.
542+ ///
525543 /// Requires that address of sender was previously passed to
526544 /// `auth_transfer`.
527545 ///
@@ -546,6 +564,35 @@ module ob_kiosk::ob_kiosk {
546564 req
547565 }
548566
567+ /// Transfer NFT out of Kiosk that has been previously delegated
568+ ///
569+ /// NFT will be locked in the target `Kiosk`.
570+ ///
571+ /// Requires that address of sender was previously passed to
572+ /// `auth_transfer`.
573+ ///
574+ /// #### Panics
575+ ///
576+ /// - Entity `UID` was not previously authorized for transfer
577+ /// - NFT does not exist
578+ /// - Target `Kiosk` deposit conditions were not met, see `deposit` method
579+ /// - Source or target `Kiosk` are not OriginByte kiosks
580+ public fun transfer_delegated_locked <T : key + store >(
581+ source: &mut Kiosk ,
582+ target: &mut Kiosk ,
583+ nft_id: ID ,
584+ entity_id: &UID ,
585+ price: u64 ,
586+ transfer_policy: &sui::transfer_policy ::TransferPolicy <T >,
587+ ctx: &mut TxContext ,
588+ ): TransferRequest <T > {
589+ assert_version_and_upgrade (ext (source));
590+
591+ let (nft, req) = transfer_nft_ (source, nft_id, uid_to_address (entity_id), price, ctx);
592+ deposit_locked (target, transfer_policy, nft, ctx);
593+ req
594+ }
595+
549596 /// Transfer NFT out of Kiosk that has been previously delegated
550597 ///
551598 /// Requires that address of sender was previously passed to
@@ -576,8 +623,10 @@ module ob_kiosk::ob_kiosk {
576623 req
577624 }
578625
579- /// Transfer NFT out of Kiosk that has been previously delegated to a base
580- /// Sui `Kiosk`
626+ /// Transfer locked NFT out of Kiosk that has been previously delegated to
627+ /// a base Sui `Kiosk`
628+ ///
629+ /// The transferred NFT is immediately locked in the target `Kiosk`.
581630 ///
582631 /// Requires that `UID` of sender was previously passed to either
583632 /// `auth_transfer` or `auth_exclusive_transfer`.
@@ -589,29 +638,81 @@ module ob_kiosk::ob_kiosk {
589638 /// - Sender was not previously authorized for transfer or is not owner
590639 /// - NFT does not exist
591640 /// - Source is not an OriginByte `Kiosk`
592- public fun transfer_locked_nft <T : key + store >(
641+ public fun transfer_locked <T : key + store >(
593642 source: &mut Kiosk ,
594643 target: &mut Kiosk ,
595644 nft_id: ID ,
596645 entity_id: &UID ,
646+ paid: Coin <sui::sui ::SUI >,
647+ transfer_policy: &sui::transfer_policy ::TransferPolicy <T >,
597648 ctx: &mut TxContext ,
598649 ): TransferRequest <T > {
599650 assert_version_and_upgrade (ext (source));
600651
601652 check_entity_and_pop_ref (source, uid_to_address (entity_id), nft_id, ctx);
602653
603654 let cap = pop_cap (source);
604- kiosk::list <T >(source, &cap, nft_id, 0 );
655+ kiosk::list <T >(source, &cap, nft_id, coin:: value (&paid) );
605656 set_cap (source, cap);
606657
607- let (nft, req) = kiosk::purchase <T >(source, nft_id, coin::zero (ctx));
658+ let (nft, req) = kiosk::purchase <T >(source, nft_id, paid);
659+ deposit_locked (target, transfer_policy, nft, ctx);
660+
661+ let req = transfer_request::from_sui <T >(req, nft_id, uid_to_address (entity_id), ctx);
662+
663+ req
664+ }
665+
666+ /// Transfer locked NFT out of Kiosk that has been previously delegated to
667+ /// a base Sui `Kiosk`
668+ ///
669+ /// The transferred NFT is not locked in the target `Kiosk`.
670+ ///
671+ /// Requires that `UID` of sender was previously passed to either
672+ /// `auth_transfer` or `auth_exclusive_transfer`.
673+ ///
674+ /// Will always work if transaction sender is the `Kiosk` owner.
675+ ///
676+ /// #### Panics
677+ ///
678+ /// - Sender was not previously authorized for transfer or is not owner
679+ /// - NFT does not exist
680+ /// - Source is not an OriginByte `Kiosk`
681+ public fun transfer_unlocked <T : key + store >(
682+ source: &mut Kiosk ,
683+ target: &mut Kiosk ,
684+ nft_id: ID ,
685+ entity_id: &UID ,
686+ paid: Coin <sui::sui ::SUI >,
687+ ctx: &mut TxContext ,
688+ ): TransferRequest <T > {
689+ assert_version_and_upgrade (ext (source));
690+
691+ check_entity_and_pop_ref (source, uid_to_address (entity_id), nft_id, ctx);
692+
693+ let cap = pop_cap (source);
694+ kiosk::list <T >(source, &cap, nft_id, coin::value (&paid));
695+ set_cap (source, cap);
696+
697+ let (nft, req) = kiosk::purchase <T >(source, nft_id, paid);
608698 deposit (target, nft, ctx);
609699
610700 let req = transfer_request::from_sui <T >(req, nft_id, uid_to_address (entity_id), ctx);
611701
612702 req
613703 }
614704
705+ /// Deprecated, use `transfer_locked` instead
706+ public fun transfer_locked_nft <T : key + store >(
707+ _source: &mut Kiosk ,
708+ _target: &mut Kiosk ,
709+ _nft_id: ID ,
710+ _entity_id: &UID ,
711+ _ctx: &mut TxContext ,
712+ ): TransferRequest <T > {
713+ abort (EDeprecatedApi )
714+ }
715+
615716 /// Withdraw NFT from `Kiosk` without returning it
616717 ///
617718 /// Requires that `UID` of sender was previously passed to either
@@ -819,6 +920,8 @@ module ob_kiosk::ob_kiosk {
819920 assert ! (kiosk::has_access (self, &kiosk_cap), ENotOwner );
820921 assert ! (!is_ob_kiosk (self), EKioskOriginByteVersion );
821922
923+ // Ensure that `uid_mut` will work
924+ kiosk::set_allow_extensions (self, &kiosk_cap, true );
822925 let kiosk_ext = ext (self);
823926
824927 df::add (kiosk_ext, VersionDfKey {}, VERSION );
@@ -849,12 +952,21 @@ module ob_kiosk::ob_kiosk {
849952 assert_version_and_upgrade (ext (self));
850953 assert_permission (self, ctx);
851954
852- // Assert that Kiosk has NFT
955+ register_nft_ (self, nft_id);
956+ }
957+
958+ /// Create an `NftRef` entry for the NFT
959+ ///
960+ /// #### Panics
961+ ///
962+ /// Panics if `NftRef` already exists
963+ fun register_nft_ (
964+ self: &mut Kiosk ,
965+ nft_id: ID ,
966+ ) {
853967 assert_has_nft (self, nft_id);
854968 assert ! (!kiosk::is_listed (self, nft_id), ENftIsListedInBaseKiosk );
855969
856- // Assert that Kiosk has no NftRef, which means the NFT was
857- // placed in the Kiosk before installing the OB extension
858970 let refs = nft_refs_mut (self);
859971 assert_missing_ref (refs, nft_id);
860972
@@ -1164,6 +1276,8 @@ module ob_kiosk::ob_kiosk {
11641276 df::exists_ (uid (self), NftRefsDfKey {})
11651277 }
11661278
1279+ /// Returns whether the current transaction sender can deposit into `Kiosk`
1280+ ///
11671281 /// Either sender is owner or permissionless deposits of `T` enabled.
11681282 public fun can_deposit <T >(self: &mut Kiosk , ctx: &mut TxContext ): bool {
11691283 sender (ctx) == kiosk::owner (self) || can_deposit_permissionlessly <T >(self)
@@ -1189,7 +1303,6 @@ module ob_kiosk::ob_kiosk {
11891303 /// Panics if `Kiosk` is not OriginByte `Kiosk`
11901304 //
11911305 // TODO: Replace with immutable API
1192- // TODO: Consider removing test_only
11931306 public fun nft_refs (self: &Kiosk ): &Table <ID , NftRef > {
11941307 is_ob_kiosk_imut (self);
11951308 df::borrow (uid (self), NftRefsDfKey {})
@@ -1221,6 +1334,11 @@ module ob_kiosk::ob_kiosk {
12211334 assert ! (is_permissionless (self), EKioskNotPermissionless );
12221335 }
12231336
1337+ /// Asserts that the transaction sender may deposit into `Kiosk`
1338+ ///
1339+ /// #### Panics
1340+ ///
1341+ /// Panics if sender is not owner or `Kiosk` is not permissionless.
12241342 public fun assert_can_deposit <T >(self: &mut Kiosk , ctx: &mut TxContext ) {
12251343 assert ! (can_deposit <T >(self, ctx), ECannotDeposit );
12261344 }
@@ -1296,7 +1414,7 @@ module ob_kiosk::ob_kiosk {
12961414 assert ! (vec_set::size (&ref.auths) == 0 , ENftAlreadyListed );
12971415 }
12981416
1299- /// Check whether NFT can be transferred by given authority
1417+ /// Check whether NFT can be transferred by given authority and remove the NftRef entry
13001418 ///
13011419 /// #### Panics
13021420 ///
@@ -1307,7 +1425,7 @@ module ob_kiosk::ob_kiosk {
13071425 entity: address ,
13081426 nft_id: ID ,
13091427 ctx: &mut TxContext ,
1310- ) {
1428+ ): NftRef {
13111429 let refs = nft_refs_mut (self);
13121430 // NFT is being transferred - destroy the ref
13131431 let ref: NftRef = table::remove (refs, nft_id);
@@ -1316,6 +1434,7 @@ module ob_kiosk::ob_kiosk {
13161434 is_owner (self, sender (ctx)) || vec_set::contains (&ref.auths, &entity),
13171435 ENotAuthorized ,
13181436 );
1437+ ref
13191438 }
13201439
13211440 /// Borrow `DepositSetting` field
0 commit comments