@layerzerolabs/lz-sui-sdk-v2
Version:
103 lines (88 loc) • 3.6 kB
text/typescript
import { ObjectOwner } from '@mysten/sui/client'
import { MoveCallWithObjectDetails } from './move-call-object-fetcher'
import { IPTBValidator } from './ptb-validator'
/**
* NonSenderObjectValidator ensures objects are not owned by the transaction sender
*
* In Sui, this validator checks that objects are:
* - Shared: globally accessible, mutations require consensus
* - Immutable: can't change after creation
* - Owned by another address (not the sender)
*
* This prevents the sender from using their own owned objects in the transaction
*/
export class NonSenderObjectValidator implements IPTBValidator {
private sender: string
constructor(sender: string) {
this.sender = sender
}
/**
* Validates that objects are not owned by the sender
* @param moveCallsWithDetails - Array of move calls with object details
* @throws Error if any object is owned by the sender
*/
validate(moveCallsWithDetails: MoveCallWithObjectDetails[]): void {
for (const { objectDetails } of moveCallsWithDetails) {
for (const [objectId, objectResponse] of objectDetails) {
const owner = objectResponse.data?.owner
if (owner == null) {
throw new Error(`Object ${objectId} has no owner`)
}
// Validate that object is not owned by the sender
if (!this.isValidOwnership(owner)) {
const ownerType = this.getOwnershipType(owner)
throw new Error(
`Object ${objectId} is owned by the sender (${this.sender}). ` +
`Only Shared, Immutable, or objects owned by other addresses are allowed. ` +
`Current ownership: ${ownerType}`
)
}
}
}
}
/**
* Checks if the ownership is valid (not owned by sender)
* @param owner - The object owner to check
* @returns true if ownership is valid (Shared, Immutable, or owned by another address)
*/
private isValidOwnership(owner: ObjectOwner): boolean {
// Shared objects are valid
if (typeof owner === 'object' && 'Shared' in owner) {
return true
}
// Immutable objects are valid
if (owner === 'Immutable') {
return true
}
// Objects owned by another address are valid
if (typeof owner === 'object' && 'AddressOwner' in owner && owner.AddressOwner !== this.sender) {
return true
}
// Objects owned by another object are valid
if (typeof owner === 'object' && 'ObjectOwner' in owner) {
return true
}
// If owned by sender, it's invalid
return false
}
/**
* Gets a human-readable description of the ownership type
* @param owner - The object owner
* @returns String description of ownership type
*/
private getOwnershipType(owner: ObjectOwner): string {
if (typeof owner === 'object' && 'Shared' in owner) {
return `Shared (initial_shared_version: ${owner.Shared.initial_shared_version})`
}
if (owner === 'Immutable') {
return 'Immutable'
}
if (typeof owner === 'object' && 'AddressOwner' in owner) {
return `AddressOwner: ${owner.AddressOwner}`
}
if (typeof owner === 'object' && 'ObjectOwner' in owner) {
return `ObjectOwner: ${owner.ObjectOwner}`
}
return 'Unknown ownership type'
}
}