@@ -147,6 +147,87 @@ CREATE POLICY token_metadata_erc721_delete ON ethereum."token_metadata_erc721"
147147FOR DELETE TO anon, authenticated, service_role
148148USING (true);
149149
150+ -- Table: ethereum.token_metadata_erc1155
151+
152+ -- DROP TABLE IF EXISTS ethereum.token_metadata_erc1155;
153+
154+ CREATE TABLE IF NOT EXISTS ethereum .token_metadata_erc1155
155+ (
156+ address text COLLATE pg_catalog." default" NOT NULL ,
157+ name text COLLATE pg_catalog." default" ,
158+ symbol text COLLATE pg_catalog." default" ,
159+ created_at timestamp with time zone NOT NULL DEFAULT now(),
160+ CONSTRAINT token_metadata_erc1155_pkey PRIMARY KEY (address),
161+ CONSTRAINT token_metadata_erc1155_address_key UNIQUE (address)
162+ );
163+
164+ ALTER TABLE IF EXISTS ethereum .token_metadata_erc1155
165+ OWNER to postgres;
166+
167+ ALTER TABLE ethereum .token_metadata_erc1155
168+ ENABLE ROW LEVEL SECURITY;
169+
170+ CREATE POLICY token_metadata_erc1155_select ON ethereum .token_metadata_erc1155
171+ FOR SELECT TO anon, authenticated, service_role
172+ USING (true);
173+
174+ CREATE POLICY token_metadata_erc1155_insert ON ethereum .token_metadata_erc1155
175+ FOR INSERT TO anon, authenticated, service_role
176+ WITH CHECK (true);
177+
178+ CREATE POLICY token_metadata_erc1155_update ON ethereum .token_metadata_erc1155
179+ FOR UPDATE TO anon, authenticated, service_role
180+ USING (true)
181+ WITH CHECK (true);
182+
183+ CREATE POLICY token_metadata_erc1155_delete ON ethereum .token_metadata_erc1155
184+ FOR DELETE TO anon, authenticated, service_role
185+ USING (true);
186+
187+ -- Table: ethereum.token_erc1155
188+
189+ -- DROP TABLE IF EXISTS ethereum.token_erc1155;
190+
191+ CREATE TABLE IF NOT EXISTS ethereum .token_erc1155
192+ (
193+ id uuid DEFAULT uuid_generate_v4() NOT NULL ,
194+ account_address text COLLATE pg_catalog." default" NOT NULL ,
195+ token_address text COLLATE pg_catalog." default" NOT NULL ,
196+ token_id numeric NOT NULL ,
197+ balance numeric NOT NULL DEFAULT 0 ,
198+ uri text COLLATE pg_catalog." default" ,
199+ last_balance_change timestamp without time zone NOT NULL DEFAULT now(),
200+ CONSTRAINT token_erc1155_pkey PRIMARY KEY (id),
201+ CONSTRAINT token_erc1155_contract_token_account_unique UNIQUE (token_address, token_id, account_address),
202+ CONSTRAINT token_erc1155_token_address_fkey FOREIGN KEY (token_address)
203+ REFERENCES ethereum .token_metadata_erc1155 (address) MATCH SIMPLE
204+ ON UPDATE NO ACTION
205+ ON DELETE NO ACTION
206+ );
207+
208+ ALTER TABLE IF EXISTS ethereum .token_erc1155
209+ OWNER to postgres;
210+
211+ ALTER TABLE ethereum .token_erc1155
212+ ENABLE ROW LEVEL SECURITY;
213+
214+ CREATE POLICY token_erc1155_select ON ethereum .token_erc1155
215+ FOR SELECT TO anon, authenticated, service_role
216+ USING (true);
217+
218+ CREATE POLICY token_erc1155_insert ON ethereum .token_erc1155
219+ FOR INSERT TO anon, authenticated, service_role
220+ WITH CHECK (true);
221+
222+ CREATE POLICY token_erc1155_update ON ethereum .token_erc1155
223+ FOR UPDATE TO anon, authenticated, service_role
224+ USING (true)
225+ WITH CHECK (true);
226+
227+ CREATE POLICY token_erc1155_delete ON ethereum .token_erc1155
228+ FOR DELETE TO anon, authenticated, service_role
229+ USING (true);
230+
150231-- Table: ethereum.token_erc721
151232
152233-- DROP TABLE IF EXISTS ethereum.token_erc721;
@@ -280,8 +361,15 @@ CREATE POLICY token_transfer_delete ON ethereum.token_transfer
280361FOR DELETE TO anon, authenticated, service_role
281362USING (true);
282363
364+ -- Adding token_id column to token_transfer for ERC-1155 support
365+ ALTER TABLE ethereum .token_transfer
366+ ADD COLUMN IF NOT EXISTS token_id numeric ;
367+
283368COMMENT ON COLUMN ethereum .token_transfer .value
284- IS ' ERC20 - token quantity, ERC721 - token ID' ;
369+ IS ' ERC20 - token quantity, ERC721 - not used (see token_id), ERC1155 - token quantity' ;
370+
371+ COMMENT ON COLUMN ethereum .token_transfer .token_id
372+ IS ' ERC721 - token ID, ERC1155 - token ID, ERC20 - not used' ;
285373
286374-- --------------------------------------------------------------------------------------------------
287375-- VIEWS
@@ -332,6 +420,31 @@ WITH (security_invoker = on)
332420ALTER TABLE ethereum .erc721_token_history_view
333421 OWNER TO postgres;
334422
423+ -- View: ethereum.erc1155_token_history_view
424+
425+ -- DROP VIEW IF EXISTS ethereum.erc1155_token_history_view;
426+
427+ CREATE OR REPLACE VIEW ethereum .erc1155_token_history_view
428+ WITH (security_invoker = on )
429+ AS
430+ SELECT
431+ tx .hash AS transaction_hash,
432+ tx." to" AS token_address,
433+ b .created_at ,
434+ tt .sender ,
435+ tt .recipient ,
436+ tt .token_id ,
437+ tt .value AS quantity
438+ FROM ethereum .transaction tx
439+ JOIN ethereum .block b ON tx .block_number = b .number
440+ JOIN ethereum .token_transfer tt ON tx .id = tt .transaction_id
441+ JOIN ethereum .token_metadata_erc1155 tkn ON tx." to" = tkn .address
442+ WHERE tt .token_id IS NOT NULL -- Ensure token_id is present (ERC-1155 or ERC-721)
443+ ORDER BY b .created_at , tt .recipient ;
444+
445+ ALTER TABLE ethereum .erc1155_token_history_view
446+ OWNER TO postgres;
447+
335448-- View: ethereum.token_erc20
336449
337450-- DROP MATERIALIZED VIEW IF EXISTS ethereum.token_erc20;
@@ -466,6 +579,104 @@ ALTER PROCEDURE ethereum.update_issued_erc721_tokens(numeric)
466579
467580GRANT EXECUTE ON PROCEDURE ethereum .update_issued_erc721_tokens (numeric ) TO public;
468581
582+ -- PROCEDURE: ethereum.update_issued_erc1155_tokens(numeric)
583+
584+ -- DROP PROCEDURE IF EXISTS ethereum.update_issued_erc1155_tokens(numeric);
585+
586+ CREATE OR REPLACE PROCEDURE ethereum .update_issued_erc1155_tokens (IN from_block_number numeric )
587+ LANGUAGE ' plpgsql'
588+ SET search_path = ethereum, public
589+ AS $BODY$
590+ DECLARE
591+ current_token_entry ethereum .token_erc1155 %ROWTYPE;
592+ token_transfer record;
593+ block_created_at timestamp ;
594+ BEGIN
595+ -- Get the block's creation time
596+ SELECT created_at
597+ FROM ethereum .block
598+ WHERE number = from_block_number
599+ INTO block_created_at;
600+
601+ IF NOT found THEN
602+ raise exception ' invalid block provided: %' , from_block_number
603+ USING hint = ' ensure that given block was synchronized correctly' ;
604+ END IF;
605+
606+ -- Process each transfer (distinct by token_address, token_id, recipient to handle batch transfers)
607+ FOR token_transfer IN SELECT
608+ *
609+ FROM ethereum .erc1155_token_history_view
610+ WHERE created_at >= block_created_at
611+ ORDER BY token_address, token_id, sender, recipient, created_at DESC
612+ LOOP
613+ -- Process sender (decrease balance)
614+ IF token_transfer .sender != ' 0x0000000000000000000000000000000000000000' THEN -- Not a mint
615+ SELECT * FROM ethereum .token_erc1155
616+ WHERE token_id = token_transfer .token_id
617+ AND token_address = token_transfer .token_address
618+ AND account_address = token_transfer .sender
619+ INTO current_token_entry;
620+
621+ IF found THEN
622+ -- Decrease sender's balance
623+ UPDATE ethereum .token_erc1155
624+ SET balance = GREATEST(0 , balance - token_transfer .quantity ),
625+ last_balance_change = token_transfer .created_at
626+ WHERE id = current_token_entry .id ;
627+
628+ -- Remove entry if balance reaches 0
629+ DELETE FROM ethereum .token_erc1155
630+ WHERE id = current_token_entry .id AND balance = 0 ;
631+ END IF;
632+ END IF;
633+
634+ -- Process recipient (increase balance)
635+ IF token_transfer .recipient != ' 0x0000000000000000000000000000000000000000' THEN -- Not a burn
636+ SELECT * FROM ethereum .token_erc1155
637+ WHERE token_id = token_transfer .token_id
638+ AND token_address = token_transfer .token_address
639+ AND account_address = token_transfer .recipient
640+ INTO current_token_entry;
641+
642+ IF NOT found THEN
643+ -- Create new entry for recipient
644+ raise notice ' create entry for token ID % on contract % for account %' ,
645+ token_transfer .token_id , token_transfer .token_address , token_transfer .recipient ;
646+ INSERT INTO ethereum .token_erc1155
647+ VALUES (
648+ uuid_generate_v4(),
649+ token_transfer .recipient ,
650+ token_transfer .token_address ,
651+ token_transfer .token_id ,
652+ token_transfer .quantity ,
653+ NULL , -- uri (can be fetched later)
654+ token_transfer .created_at
655+ );
656+ ELSE
657+ -- Increase recipient's balance
658+ IF current_token_entry .last_balance_change < token_transfer .created_at THEN
659+ raise notice ' update balance for token ID % on contract % for account %' ,
660+ token_transfer .token_id , token_transfer .token_address , token_transfer .recipient ;
661+ UPDATE ethereum .token_erc1155
662+ SET balance = balance + token_transfer .quantity ,
663+ last_balance_change = token_transfer .created_at
664+ WHERE id = current_token_entry .id ;
665+ ELSE
666+ raise notice ' current entry is more recent - ignore token ID % on contract % for account %' ,
667+ token_transfer .token_id , token_transfer .token_address , token_transfer .recipient ;
668+ END IF;
669+ END IF;
670+ END IF;
671+ END LOOP;
672+ END
673+ $BODY$;
674+
675+ ALTER PROCEDURE ethereum .update_issued_erc1155_tokens (numeric )
676+ OWNER TO postgres;
677+
678+ GRANT EXECUTE ON PROCEDURE ethereum .update_issued_erc1155_tokens (numeric ) TO public;
679+
469680-- FUNCTION: ethereum.get_missing_blocks_in_range(integer, integer)
470681
471682-- DROP FUNCTION IF EXISTS ethereum.get_missing_blocks_in_range(integer, integer);
0 commit comments