Skip to content

Commit

Permalink
Add last transferred timestamp (#78)
Browse files Browse the repository at this point in the history
* Add last transferred timestamp

* Fix formatting
  • Loading branch information
febo authored Jun 7, 2024
1 parent 3e80f3a commit 99d21e9
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 5 deletions.
4 changes: 4 additions & 0 deletions clients/js/proxy/test/_setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,7 @@ export const STUB_KEY = Uint8Array.from([
198, 193, 21, 158, 198, 203, 241, 229, 179, 162, 229, 129, 109, 151, 51, 135,
240, 128, 114, 242, 103, 170, 154, 47, 218, 130, 218, 139, 45, 47,
]);

export function sleep(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
18 changes: 17 additions & 1 deletion clients/js/proxy/test/transfer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,17 @@ import {
ExtensionType,
Standard,
State,
Type,
fetchAsset,
getExtension,
getProperty,
transfer,
} from '@nifty-oss/asset';
import { Keypair } from '@solana/web3.js';
import test from 'ava';
import { create } from '../src';
import { findProxiedAssetPda } from '../src/pda';
import { STUB_KEY, createUmi } from './_setup';
import { STUB_KEY, createUmi, sleep } from './_setup';

test('it cannot transfer a non-signer proxied asset', async (t) => {
// Given a Umi instance and a new signer.
Expand Down Expand Up @@ -114,6 +116,12 @@ test('it can execute custom logic on transfer', async (t) => {
const initial = attributes?.values[0].value;
t.true(parseInt(initial!) === 0);

// initial value for the last transferred timestamp
const timestamp = getProperty(asset, 'last_transferred', Type.Number)!.value;

// We wait for a second to ensure the timestamp is different.
await sleep(1000);

const recipient = generateSigner(umi).publicKey;
const proxy = getExtension(asset, ExtensionType.Proxy);
// And we transfer the proxied asset through the proxy program (using
Expand All @@ -139,6 +147,14 @@ test('it can execute custom logic on transfer', async (t) => {
const current = parseInt(attributes?.values[0].value!);
t.true(current === 1);
t.assert(parseInt(initial!) < current);

// And the last transferred timestamp is updated.
const lastTransferred = getProperty(
asset,
'last_transferred',
Type.Number
)!.value;
t.assert(timestamp < lastTransferred);
});

test('it can transfer the proxy asset multiple times', async (t) => {
Expand Down
20 changes: 17 additions & 3 deletions programs/proxy/src/processor/create.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
use nifty_asset_interface::{
extensions::{AttributesBuilder, BlobBuilder, ExtensionBuilder, ProxyBuilder},
extensions::{
AttributesBuilder, BlobBuilder, ExtensionBuilder, PropertiesBuilder, ProxyBuilder,
},
instructions::CreateCpiBuilder,
types::ExtensionInput,
ExtensionType, Standard,
};
use solana_program::{entrypoint::ProgramResult, program_error::ProgramError, pubkey::Pubkey};
use solana_program::{
clock::Clock, entrypoint::ProgramResult, program_error::ProgramError, pubkey::Pubkey,
sysvar::Sysvar,
};

use crate::{
instruction::{
Expand Down Expand Up @@ -86,6 +91,15 @@ pub fn process_create(
data: Some(data),
};

let data = PropertiesBuilder::with_capacity(30)
.add_number("last_transferred", Clock::get()?.unix_timestamp as u64)
.data();
let properties = ExtensionInput {
extension_type: ExtensionType::Properties,
length: data.len() as u32,
data: Some(data),
};

// creates the proxied asset

CreateCpiBuilder::new(ctx.accounts.nifty_asset_program)
Expand All @@ -97,6 +111,6 @@ pub fn process_create(
.system_program(ctx.accounts.system_program)
.name(metadata.name)
.standard(Standard::Proxied)
.extensions(vec![attributes, blob, proxy])
.extensions(vec![attributes, blob, proxy, properties])
.invoke_signed(&[&signer])
}
18 changes: 17 additions & 1 deletion programs/proxy/src/processor/transfer.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use nifty_asset_interface::{
accounts::TransferAccounts,
extensions::{Attributes, AttributesBuilder, BlobBuilder, ExtensionBuilder},
extensions::{Attributes, AttributesBuilder, BlobBuilder, ExtensionBuilder, PropertiesBuilder},
fetch_proxy_data,
instructions::{TransferCpiBuilder, UpdateCpiBuilder},
state::Asset,
Expand Down Expand Up @@ -93,6 +93,22 @@ pub fn process_transfer<'a>(
})
.invoke_signed(&[&signer])?;

// updates the properties (last tranferred)

let data = PropertiesBuilder::with_capacity(30)
.add_number("last_transferred", Clock::get()?.unix_timestamp as u64)
.data();

UpdateCpiBuilder::new(nifty_asset_program)
.asset(ctx.accounts.asset)
.authority(ctx.accounts.asset)
.extension(ExtensionInput {
extension_type: ExtensionType::Properties,
length: data.len() as u32,
data: Some(data),
})
.invoke_signed(&[&signer])?;

// cpi into the Nifty Asset program to perform the transfer

TransferCpiBuilder::new(nifty_asset_program)
Expand Down

0 comments on commit 99d21e9

Please sign in to comment.