Skip to content

Commit

Permalink
[CP] Shorten NFT URL (aptos-labs#4033)
Browse files Browse the repository at this point in the history
* [CP] Shorten NFT URL

Update controller to fetch by version.

Update links once we get the version.

* Fix brakeman warning.

Co-authored-by: Zach Denton <[email protected]>
  • Loading branch information
CapCap and zacharydenton authored Sep 9, 2022
1 parent 87b2ddf commit 0c26e9c
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class NftImagesController < ApplicationController
include ActiveStorage::SetCurrent

def show
@nft_offer = NftOffer.find(params[:nft_offer_slug])
@nft_offer = NftOffer.find_by(slug: params[:nft_offer_slug])
@image_num = params[:image_num].to_i
unless @image_num.positive? && @image_num <= MAX_IMAGE_NUM_ALLOWED
render plain: nil,
Expand Down
15 changes: 12 additions & 3 deletions ecosystem/platform/server/app/controllers/nft_offers_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,26 @@
class NftOffersController < ApplicationController
before_action :authenticate_user!, only: %i[create]

def short
@nft_offer = NftOffer.find(params[:offer_id])
redirect_to nft_offer_path(slug: @nft_offer.slug, v: params[:txn_version])
end

def show
@image_dialog = DialogComponent.new(id: 'image_dialog', class: '!w-max max-h-max')
store_location_for(:user, request.path)
@nft_offer = NftOffer.find(params[:slug])
@nft_offer = NftOffer.find_by(slug: params[:slug])
@wallet = current_user&.wallets&.find_by(network: @nft_offer.network, public_key: params[:wallet]) ||
Wallet.new(network: @nft_offer.network, challenge: 24.times.map { rand(10) }.join)

@transaction_hash = params[:txn]
@transaction_version = params[:v].to_i

return render :minted if @transaction_hash.is_a?(String) && @transaction_hash.match?(/^0x[0-9a-f]{64}$/)
txn_hash_valid = @transaction_hash.is_a?(String) && @transaction_hash.match?(/^0x[0-9a-f]{64}$/)
txn_version_valid = @transaction_version.positive?
return render :minted if txn_hash_valid || txn_version_valid

@transaction_version = nil
@transaction_hash = nil

@steps = [
Expand All @@ -33,7 +42,7 @@ def show
end

def update
@nft_offer = NftOffer.find(params[:slug])
@nft_offer = NftOffer.find_by(slug: params[:slug])
@wallet = current_user.wallets.find_by(network: @nft_offer.network, public_key: params[:wallet])

result = NftClaimer.new.claim_nft(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

import { Controller } from "./controller";
import type { FrameElement } from "@hotwired/turbo/dist/types/elements";
import type { Types } from "aptos";

function hexToAscii(hex: string) {
Expand All @@ -20,6 +21,7 @@ function decodeMintNumber(mintNumber: string) {
export default class extends Controller {
static values = {
transactionHash: String,
transactionVersion: Number,
apiUrl: String,
};

Expand All @@ -29,15 +31,18 @@ export default class extends Controller {
"mintNumber",
"image",
"address",
"transactionLinks",
];

declare readonly transactionFailedErrorTarget: HTMLElement;
declare readonly dateMintedTarget: HTMLElement;
declare readonly mintNumberTargets: HTMLElement[];
declare readonly addressTarget: HTMLElement;
declare readonly imageTargets: HTMLImageElement[];
declare readonly transactionLinksTarget: FrameElement;

declare readonly transactionHashValue: string;
declare readonly transactionHashValue: string | null;
declare readonly transactionVersionValue: number | null;
declare readonly apiUrlValue: string;

retries = 0;
Expand All @@ -46,14 +51,28 @@ export default class extends Controller {
this.fetchNftInfo();
}

get transactionUrl() {
if (this.transactionVersionValue) {
return [
this.apiUrlValue,
"transactions",
"by_version",
this.transactionVersionValue,
].join("/");
} else if (this.transactionHashValue) {
return [
this.apiUrlValue,
"transactions",
"by_hash",
this.transactionHashValue,
].join("/");
} else {
throw "unable to determine transaction url";
}
}

fetchNftInfo = async () => {
const transactionUrl = [
this.apiUrlValue,
"transactions",
"by_hash",
this.transactionHashValue,
].join("/");
const response = await fetch(transactionUrl);
const response = await fetch(this.transactionUrl);
if (!response.ok && ++this.retries <= 1) {
return setTimeout(this.fetchNftInfo, 1000);
}
Expand All @@ -67,6 +86,15 @@ export default class extends Controller {
return;
}

const urlParams = new URLSearchParams(location.search);
if (!urlParams.get("v")) {
urlParams.delete("txn");
urlParams.set("v", transaction.version);
const url = new URL(location.href);
url.search = urlParams.toString();
this.transactionLinksTarget.src = url.toString();
}

const createEvent = transaction.events.find(
(event) => event.type === "0x3::token::CreateTokenDataEvent"
);
Expand Down
6 changes: 3 additions & 3 deletions ecosystem/platform/server/app/models/nft_image.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class NftImage < ApplicationRecord

def self.find_or_create(slug, image_num)
# Verify this is a valid slug
nft_offer = NftOffer.find(slug)
nft_offer = NftOffer.find_by(slug:)
# Find or create the nft_image
img, is_new = NftImageQueryHelper._find_or_create(nft_offer, image_num)

Expand Down Expand Up @@ -64,7 +64,7 @@ def self.find_or_create(slug, image_num)

# Returns a `TempFile` with the image contents
def self.create_image(slug, image_num)
case NftOffer.find(slug).slug
case NftOffer.find_by(slug:).slug
when NftOffer::APTOS_ZERO
create_aptos_zero_image image_num
end
Expand Down Expand Up @@ -117,6 +117,6 @@ def self.compress_image(imagemagick_image)
end

def nft_offer
NftOffer.find(slug)
NftOffer.find_by(slug:)
end
end
16 changes: 15 additions & 1 deletion ecosystem/platform/server/app/models/nft_offer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,17 @@ class NftOffer
# Constants for slugs
APTOS_ZERO = 'aptos-zero'

def self.find(slug)
ID_TO_SLUG = {
0 => APTOS_ZERO
}.freeze

SLUG_TO_ID = ID_TO_SLUG.invert.freeze

def self.find(id)
find_by(slug: ID_TO_SLUG.fetch(id.to_i, ''))
end

def self.find_by(slug:)
case slug
when APTOS_ZERO
NftOffer.new(
Expand All @@ -27,6 +37,10 @@ def self.find(slug)
end
end

def id
SLUG_TO_ID[slug]
end

def private_key_bytes
[private_key[2..]].pack('H*')
end
Expand Down
18 changes: 15 additions & 3 deletions ecosystem/platform/server/app/views/nft_offers/minted.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<% content_for(:meta) do %>
<meta property="og:image" content="<%= image_url('meta/aptos_meta_og_nft-aptos-zero.jpg') %>">
<% end %>
<div class="bg-neutral-900 text-neutral-100 h-full" data-controller="minted-nft" data-minted-nft-transaction-hash-value="<%= @transaction_hash %>" data-minted-nft-api-url-value="<%= @wallet.api_url %>">
<div class="bg-neutral-900 text-neutral-100 h-full" data-controller="minted-nft" data-minted-nft-transaction-hash-value="<%= @transaction_hash %>" data-minted-nft-transaction-version-value="<%= @transaction_version %>" data-minted-nft-api-url-value="<%= @wallet.api_url %>">
<div class="max-w-screen-2xl mx-auto px-6 pb-24">
<section class="py-12 lg:py-32">
<h3 class="text-base uppercase text-teal-400 mb-4 font-mono">Community</h3>
Expand Down Expand Up @@ -40,20 +40,32 @@
<dt class="text-right normal-case" data-minted-nft-target="address">#</dt>
</dl>
<hr class="border-t-2 border-dotted border-neutral-400 mb-8">
<%= turbo_frame_tag :transaction_links, data: { minted_nft_target: 'transactionLinks' } do %>
<ul>
<li class="mb-4">
<%= link_to "https://explorer.devnet.aptos.dev/txn/#{@transaction_hash}?network=#{@wallet.network}", class: 'font-mono uppercase text-base text-teal-400 hover:text-teal-300 flex gap-2', target: '_blank' do %>
<% explorer_url = if @transaction_version
"https://explorer.devnet.aptos.dev/txn/#{@transaction_version}?network=#{@wallet.network}"
else
"https://explorer.devnet.aptos.dev/txn/#{CGI.escape @transaction_hash}?network=#{@wallet.network}"
end %>
<%= link_to explorer_url, class: 'font-mono uppercase text-base text-teal-400 hover:text-teal-300 flex gap-2', target: '_blank' do %>
<%= render IconComponent.new(:search, class: 'w-5') %>
View in Explorer
<% end %>
</li>
<li>
<%= link_to "http://twitter.com/intent/tweet?url=#{CGI.escape(request.url)}&text=Check%20out%20my%20APTOS%20%3A%20ZERO%20Testnet%20NFT&hashtags=AptosNFTs", class: 'font-mono uppercase text-base text-teal-400 hover:text-teal-300 flex gap-2', target: '_blank' do %>
<% twitter_url = if @transaction_version
nft_offer_short_url(offer_id: @nft_offer.id, txn_version: @transaction_version)
else
request.url
end %>
<%= link_to "http://twitter.com/intent/tweet?url=#{CGI.escape(twitter_url)}&text=Check%20out%20my%20APTOS%20%3A%20ZERO%20Testnet%20NFT&hashtags=AptosNFTs", class: 'font-mono uppercase text-base text-teal-400 hover:text-teal-300 flex gap-2', target: '_blank' do %>
<%= render IconComponent.new(:twitter, class: 'w-5') %>
Share on Twitter
<% end %>
</li>
</ul>
<% end %>
<% end %>
<div class="md:col-start-8 md:col-end-13 lg:col-span-5 lg:col-start-8 order-first md:order-last">
<%= render CardOutlineComponent.new(scheme: :filled) do %>
Expand Down
3 changes: 2 additions & 1 deletion ecosystem/platform/server/config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@

# NFTs
resources :nft_offers, param: :slug, only: %i[show update]
get 'nft_images/:nft_offer_slug/:image_num', { to: 'nft_images#show', constraints: { image_num: /\d+/ } }
get 'nft_images/:nft_offer_slug/:image_num', to: 'nft_images#show', constraints: { image_num: /\d+/ }
get 'n/:offer_id/:txn_version', as: 'nft_offer_short', to: 'nft_offers#short', constraints: { txn_version: /\d+/ }

# Leaderboards
get 'leaderboard/it1', to: redirect('/it1')
Expand Down

0 comments on commit 0c26e9c

Please sign in to comment.