Skip to content

Commit

Permalink
Merge branch 'beta'
Browse files Browse the repository at this point in the history
  • Loading branch information
zapaz committed Oct 25, 2024
2 parents cd13c1d + 56256dc commit 5c8ad66
Show file tree
Hide file tree
Showing 19 changed files with 347 additions and 32 deletions.
8 changes: 6 additions & 2 deletions common/src/common/ipfs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class Ipfs {
}

// eslint-disable-next-line @typescript-eslint/require-await,@typescript-eslint/no-unused-vars
async pin(buffer: Blob | string, options?: RequestInit): Promise<string> {
async pin(src: File | Blob | string, options?: RequestInit): Promise<string> {
return "Ipfs.pin is abstract";
}

Expand All @@ -27,6 +27,10 @@ class Ipfs {
return cid;
}

async pinFile(media: File, options?: RequestInit): Promise<string> {
return await this.pin(media, options);
}

async pinUrl(url: string, options?: RequestInit): Promise<string> {
return await this.pin(await (await fetch(url)).blob(), options);
}
Expand All @@ -42,7 +46,7 @@ class Ipfs {
return await this.add(buffer, options);
}

async pinJson(object: unknown, options?: RequestInit): Promise<string> {
async pinJson(object: object, options?: RequestInit): Promise<string> {
return await this.pin(this.jsonPrepare(object), options);
}

Expand Down
10 changes: 5 additions & 5 deletions common/src/storage/ipfs.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type { NftMetadata, NftType, Properties } from "../common/types";

import NftStorage from "./nftstorage";
import PinataStorage from "./pinataStorage";
import { textShort, DEFAULT_NAME, urlToLink } from "../common/config";
import { storageDefault, storageParamsGet, storageParamsValid } from "./storage";

let nftStorage: NftStorage;
let pinataStorage: PinataStorage;

/////////////////////////////////////////////////////////////////////////////////////////////////////
// IPFS helpers
Expand Down Expand Up @@ -94,8 +94,8 @@ const ipfsApiKey = (): string => storageParamsGet("ipfs")?.apiKey || "";

// GET ipfs uri from media url
const ipfsPin = async (mediaUrl: string): Promise<string> => {
nftStorage ||= new NftStorage();
const ipfsCid = await nftStorage.pinUrl(mediaUrl);
pinataStorage ||= new PinataStorage();
const ipfsCid = await pinataStorage.pinUrl(mediaUrl);
const ipfsUri = ipfsCid ? `ipfs://${ipfsCid}` : "";

// console.log("ipfsUri", ipfsUri);
Expand Down Expand Up @@ -129,7 +129,7 @@ const ipfsTokenUri = async (
if (animation_url) json.animation_url = ipfsGatewayUrl(animation_url);
if (pdfUri) json.pdf = ipfsGatewayUrl(pdfUri);

const ipfsJsonCid = await nftStorage.pinJson(json);
const ipfsJsonCid = await pinataStorage.pinJson(json);
const ipfsTokenUri = ipfsJsonCid && `ipfs://${ipfsJsonCid}`;

// console.log("ipfsTokenUri", ipfsTokenUri);
Expand Down
60 changes: 60 additions & 0 deletions common/src/storage/pinataStorage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import Ipfs from "../common/ipfs";
import { ipfsApiEndpoint, ipfsApiKey } from "./ipfs";

type PinataResponse = {
IpfsHash: string;
PinSize: number;
Timestamp: string;
};

class PinataStorage extends Ipfs {
key: string;

constructor() {
super(ipfsApiEndpoint());
this.key = ipfsApiKey();
}

///////////////////////////////////////////////
// see : https://docs.pinata.cloud/api-reference/endpoint/ipfs/pin-file-to-ipfs
// ( if Pinata SDK librarie is needed : https://docs.pinata.cloud/web3/tools/pinata-sdk )
async pin(src: File | Blob | string): Promise<string> {
const pinataEndpoint = `${this.endpoint}`;
const pinataJwt = this.key;

let response: PinataResponse;
let cid = "";

try {
const data = new FormData();
if (typeof src === "string") {
src = new Blob([src], { type: "application/json" });
}
data.append("file", src);

const options = JSON.stringify({ cidVersion: 1 });
data.append("pinataOptions", options);

const request = await fetch(`${pinataEndpoint}/pinning/pinFileToIPFS`, {
method: "POST",
body: data,
headers: {
Authorization: "Bearer " + pinataJwt
}
});

if (request.ok) {
response = (await request.json()) as PinataResponse;
cid = response.IpfsHash;
}

// console.log("pin ~ cid:", cid);
} catch (error) {
console.error(error);
}

return cid;
}
}

export default PinataStorage;
4 changes: 2 additions & 2 deletions config/src/config.handlebars.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
"default": "ipfs",
"ipfs": {
"gateway": "https://nftstorage.link/ipfs",
"apiEndpoint": "https://api.nft.storage",
"apiKey": "{{NFT_STORAGE_KEY}}"
"apiEndpoint": "https://api.pinata.cloud",
"apiKey": "{{PINATA_API_KEY}}"
},
"swarm": {
"gateway": "https://api.gateway.ethswarm.org/bzz",
Expand Down
2 changes: 2 additions & 0 deletions config/turbo.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
"ETHERSCAN_API_KEY_TAIKO",
"INFURA_API_KEY",
"NFT_STORAGE_KEY",
"PINATA_API_KEY",
"SWARM_API_KEY",
"THEGRAPH_KEY",
"TREASURY_ACCOUNT"
],
Expand Down
2 changes: 1 addition & 1 deletion contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"license": "ISC",
"main": "index.js",
"scripts": {
"clean": "rm -rf $HOME/.foundry cache-forge out node_modules lib types artifacts broadcast .turbo && git restore lib",
"clean": "rm -rf $HOME/.foundry/bin cache-forge out node_modules lib types artifacts broadcast .turbo && git restore lib",
"postinstall": "pnpm forge:install && pnpm forge:update",
"build": "pnpm build:forge && pnpm build:typechain",
"build:forge": "forge build",
Expand Down
6 changes: 5 additions & 1 deletion gulp/src/scss/_global.scss
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ img {
height: auto;
}

pre {
font-family: $font-family;
}

figure {
margin: 0;
padding: 0;
Expand All @@ -70,4 +74,4 @@ figure {
display: flex;
flex-wrap: wrap;
}
}
}
1 change: 1 addition & 0 deletions svelte/rollup.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const toRollupConfig = function (): RollupOptions {
format: "iife",
experimentalMinChunkSize: 100_000,
file: "./web/dapp/assets/js/kredeum-nfts.js"
// inlineDynamicImports: true
}
],
plugins: [
Expand Down
165 changes: 165 additions & 0 deletions svelte/src/components/Global/AlertModal.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
<script lang="ts">
import { onMount } from "svelte";
import { fade, fly } from "svelte/transition";
import { quintOut, bounceOut } from "svelte/easing";
import { clickOutside } from "../../helpers/clickOutside";
let open = false;
let status = "";
let title = "";
let alertMsg = "";
let alertTimeoutId: ReturnType<typeof setTimeout>;
interface KreAlertEvent extends Event {
detail: {
status: string;
title: string;
text: string;
};
}
onMount(() => {
if (window) {
window.addEventListener("KreAlertEvent", (event) => {
const alert = event as KreAlertEvent;
status = alert.detail.status;
title = alert.detail.title;
alertMsg = alert.detail.text;
open = true;
});
// Global Error Listener for Uncaught Exceptions
// window.onerror = function (message, source, lineno, colno, error) {
// // console.log("Global error:", { message, source, lineno, colno, error });
// status = "error";
// title = `${error?.name}`;
// alertMsg = error?.message || "";
// open = true;
// };
// // Global Listener for Unhandled Promise Rejections
// window.onunhandledrejection = function (event) {
// console.log("Unhandled rejection:", event);
// status = "error";
// title = `Unhandled rejection #${event.reason.code}`;
// alertMsg = event.reason.message;
// open = true;
// };
}
});
//////////////////////////////////
const alertEasingMode = () => (status === "error" ? bounceOut : quintOut);
$: alertMsg && alertDisplay();
const alertDisplay = () => {
clearTimeout(alertTimeoutId);
if (status !== "error") alertTimeoutId = setTimeout(() => alertReset(), 4000);
};
const alertReset = () => {
open = false;
status = "";
title = "";
alertMsg = "";
clearTimeout(alertTimeoutId);
};
</script>

{#if open}
<dialog
class="kre-alert-message kre-{status}-message"
role="alert"
in:fly={{ delay: 0, duration: 300, x: 0, y: 100, opacity: 0.5, easing: alertEasingMode() }}
out:fade={{ duration: 500 }}
use:clickOutside={alertReset}
{open}
>
<button on:click={alertReset} on:keydown={alertReset} class="modal-close" title="Close" aria-label="Close">
<i class="fa fa-times" />
</button>
<p class="kre-msg-title">
{#if status === "error"}
<i class="fas fa-exclamation-circle" />
{:else if status === "success"}
<i class="fas fa-check-circle" />
{:else}
<i class="fas fa-info-circle"></i>
{/if}
<span>{title || ""}</span>
</p>
<div>
<pre>{alertMsg || ""}</pre>
</div>
</dialog>
{/if}

<style>
.kre-alert-message {
background-color: #fff;
border-radius: 6px;
position: fixed;
left: 50%;
bottom: 3em;
transform: translateX(-50%);
margin: 0;
padding: 2.3em 4em 2.3em 4.5em;
max-width: 90%;
color: #000;
border-color: transparent;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
z-index: 10000;
}
.kre-msg-title {
font-weight: 700;
font-size: 1.5em;
margin-left: -1.6em;
}
.kre-msg-title i {
vertical-align: baseline;
}
span {
margin-left: 0.3em;
}
.kre-alert-message div {
max-height: 20vh;
overflow-y: auto;
}
.modal-close {
position: absolute;
top: 0.8em;
right: 0.8em;
border: none;
background-color: transparent;
cursor: pointer;
}
.modal-close i {
font-size: 1.5em;
color: rgba(30, 30, 67, 0.4);
}
.fa-exclamation-circle {
color: red;
}
.fa-check-circle {
color: rgb(16, 163, 16);
}
.fa-info-circle {
color: orange;
}
pre {
margin: 0;
white-space: pre-line;
word-wrap: break-word;
}
</style>
2 changes: 2 additions & 0 deletions svelte/src/components/Main/Dapp.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import { refPage2UrlHash, refPageFromUrlHash } from "../../helpers/refPage";
import { metamaskInit, metamaskSwitchChain } from "../../helpers/metamask";
import { metamaskChainId, metamaskSignerAddress } from "../../stores/metamask";
import AlertModal from "../Global/AlertModal.svelte";
////////////////////////////////////////////////////////////////////
// <Dapp />
Expand Down Expand Up @@ -127,6 +128,7 @@
</span>

<span slot="header">
<AlertModal />
<Title />

{#if $metamaskSignerAddress}
Expand Down
8 changes: 4 additions & 4 deletions svelte/src/components/Nft/NftClaim.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts">
import NftStorage from "@kredeum/common/src/storage/nftstorage";
import PinataStorage from "@kredeum/common/src/storage/pinataStorage";
import {
getOpenBound,
explorerTxLog,
Expand Down Expand Up @@ -31,7 +31,7 @@
let claiming = false;
let claimed = false;
let nftStorage: NftStorage;
let pinataStorage: PinataStorage;
let claimingError = "";
$: claimingError && console.error(claimingError);
Expand Down Expand Up @@ -63,8 +63,8 @@
// console.log("CLAIM", chainId, address, tokenID, tokenURI, targetChainId, targetAddress);
nftStorage ||= new NftStorage();
const cid = await nftStorage.pinUrl(storageLinkToUrlHttp(tokenURI));
pinataStorage ||= new PinataStorage();
const cid = await pinataStorage.pinUrl(storageLinkToUrlHttp(tokenURI));
if (!cid.startsWith("bafkrei")) {
claimingError = `Not CID V1 raw ${cid}`;
Expand Down
Loading

0 comments on commit 5c8ad66

Please sign in to comment.